merge with mbgl-config
This commit is contained in:
@@ -18,6 +18,22 @@
|
||||
{ 'files': [ '<(PRODUCT_DIR)/libmbgl-<(platform).a' ], 'destination': '<(install_prefix)/lib' },
|
||||
{ 'files': [ '../include/mbgl' ], 'destination': '<(install_prefix)/include' }
|
||||
],
|
||||
'actions': [
|
||||
{ 'action_name': 'mbgl-config',
|
||||
'inputs': [
|
||||
'../utils/mbgl-config/mbgl-config.template.sh',
|
||||
'../utils/mbgl-config/build.sh',
|
||||
],
|
||||
'outputs': [
|
||||
'<(install_prefix)/bin/mbgl-config',
|
||||
],
|
||||
'action': [
|
||||
'./utils/mbgl-config/build.sh',
|
||||
'<(install_prefix)',
|
||||
'<(platform)',
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
]
|
||||
}],
|
||||
|
||||
75
gyp/mbgl.gypi
Normal file
75
gyp/mbgl.gypi
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
'targets': [
|
||||
{ 'target_name': 'mbgl',
|
||||
'product_name': 'mbgl',
|
||||
'type': 'static_library',
|
||||
'standalone_static_library': 1,
|
||||
'hard_dependency': 1,
|
||||
'dependencies': [
|
||||
'shaders',
|
||||
],
|
||||
'sources': [
|
||||
'<!@(find src -name "*.cpp")',
|
||||
'<!@(test -f "config/constants_local.cpp" && echo "config/constants_local.cpp" || echo "config/constants.cpp")',
|
||||
'<!@(find src -name "*.c")',
|
||||
'<!@(find src -name "*.h")',
|
||||
'<!@(find include -name "*.hpp")',
|
||||
'<!@(find include -name "*.h")',
|
||||
'<!@(find src -name "*.glsl")',
|
||||
'bin/style.json'
|
||||
],
|
||||
'include_dirs': [
|
||||
'../include'
|
||||
],
|
||||
'conditions': [
|
||||
['OS == "mac"', {
|
||||
'xcode_settings': {
|
||||
'PUBLIC_HEADERS_FOLDER_PATH': 'include',
|
||||
'OTHER_CPLUSPLUSFLAGS': [
|
||||
'<@(png_cflags)',
|
||||
'<@(uv_cflags)',
|
||||
'<@(sqlite3_cflags)',
|
||||
'<@(zlib_cflags)',
|
||||
'-I<(boost_root)/include',
|
||||
],
|
||||
'OTHER_CFLAGS': [
|
||||
'<@(uv_cflags)',
|
||||
],
|
||||
},
|
||||
}, {
|
||||
'cflags': [
|
||||
'<@(png_cflags)',
|
||||
'<@(uv_cflags)',
|
||||
'<@(sqlite3_cflags)',
|
||||
'<@(zlib_cflags)',
|
||||
'-I<(boost_root)/include',
|
||||
],
|
||||
}]
|
||||
],
|
||||
'direct_dependent_settings': {
|
||||
'include_dirs': [
|
||||
'../include',
|
||||
],
|
||||
'conditions': [
|
||||
['OS == "mac"', {
|
||||
'xcode_settings': {
|
||||
'OTHER_LDFLAGS': [
|
||||
'<@(png_libraries)',
|
||||
'<@(uv_libraries)',
|
||||
'<@(sqlite3_libraries)',
|
||||
'<@(zlib_libraries)',
|
||||
]
|
||||
}
|
||||
}, {
|
||||
'libraries': [
|
||||
'<@(png_libraries)',
|
||||
'<@(uv_libraries)',
|
||||
'<@(sqlite3_libraries)',
|
||||
'<@(zlib_libraries)',
|
||||
]
|
||||
}]
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <mbgl/geometry/binpack.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
@@ -26,7 +27,6 @@ class SpriteAtlas : public util::noncopyable {
|
||||
public:
|
||||
typedef uint16_t dimension;
|
||||
|
||||
public:
|
||||
// Add way to construct this from another SpriteAtlas (e.g. with another pixelRatio)
|
||||
SpriteAtlas(dimension width, dimension height);
|
||||
~SpriteAtlas();
|
||||
@@ -34,22 +34,16 @@ public:
|
||||
// Changes the pixel ratio.
|
||||
bool resize(float newRatio);
|
||||
|
||||
// Update uninitialized (= outdated) sprites in this atlas from the given sprite.
|
||||
void update(const Sprite &sprite);
|
||||
// Changes the source sprite.
|
||||
void setSprite(util::ptr<Sprite> sprite);
|
||||
|
||||
// Returns the coordinates of an image that is sourced from the sprite image.
|
||||
// This getter attempts to read the image from the sprite if it is already loaded.
|
||||
// In that case, it copies it into the sprite atlas and returns the dimensions.
|
||||
// Otherwise, it returns a 0/0/0/0 rect.
|
||||
Rect<dimension> getImage(const std::string &name, const Sprite &sprite);
|
||||
Rect<dimension> getImage(const std::string& name);
|
||||
|
||||
// Returns the coordinates of an image that is sourced from the sprite image.
|
||||
// This getter waits until the sprite image was loaded, copies it into the sprite
|
||||
// image and returns the dimensions.
|
||||
// NEVER CALL THIS FUNCTION FROM THE RENDER THREAD! it is blocking.
|
||||
Rect<dimension> waitForImage(const std::string &name, const Sprite &sprite);
|
||||
|
||||
SpriteAtlasPosition getPosition(const std::string &name, const Sprite &sprite, bool repeating = false);
|
||||
SpriteAtlasPosition getPosition(const std::string& name, bool repeating = false);
|
||||
|
||||
// Binds the image buffer of this sprite atlas to the GPU, and uploads data if it is out
|
||||
// of date.
|
||||
@@ -61,19 +55,18 @@ public:
|
||||
inline float getTextureHeight() const { return height * pixelRatio; }
|
||||
inline float getPixelRatio() const { return pixelRatio; }
|
||||
|
||||
private:
|
||||
void allocate();
|
||||
Rect<SpriteAtlas::dimension> allocateImage(size_t width, size_t height);
|
||||
void copy(const Rect<dimension> &dst, const SpritePosition &src, const Sprite &sprite);
|
||||
|
||||
public:
|
||||
const dimension width = 0;
|
||||
const dimension height = 0;
|
||||
|
||||
private:
|
||||
std::mutex mtx;
|
||||
void allocate();
|
||||
Rect<SpriteAtlas::dimension> allocateImage(size_t width, size_t height);
|
||||
void copy(const Rect<dimension>& dst, const SpritePosition& src);
|
||||
|
||||
std::recursive_mutex mtx;
|
||||
float pixelRatio = 1.0f;
|
||||
BinPack<dimension> bin;
|
||||
util::ptr<Sprite> sprite;
|
||||
std::map<std::string, Rect<dimension>> images;
|
||||
std::set<std::string> uninitialized;
|
||||
uint32_t *data = nullptr;
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
#include <mbgl/map/transform.hpp>
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
|
||||
#include <mbgl/geometry/glyph_atlas.hpp>
|
||||
#include <mbgl/geometry/sprite_atlas.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/time.hpp>
|
||||
#include <mbgl/util/uv.hpp>
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <atomic>
|
||||
#include <iosfwd>
|
||||
@@ -17,10 +17,8 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class GlyphAtlas;
|
||||
class GlyphStore;
|
||||
class LayerDescription;
|
||||
class SpriteAtlas;
|
||||
class Sprite;
|
||||
class Style;
|
||||
class StyleLayer;
|
||||
@@ -55,8 +53,6 @@ public:
|
||||
// Triggers a lazy rerender: only performs a render when the map is not clean.
|
||||
void rerender();
|
||||
|
||||
void renderLayer(util::ptr<StyleLayer> layer_desc, RenderPass pass, const Tile::ID* id = nullptr, const mat4* matrix = nullptr);
|
||||
|
||||
// Forces a map update: always triggers a rerender.
|
||||
void update();
|
||||
|
||||
@@ -133,12 +129,11 @@ public:
|
||||
inline const TransformState &getState() const { return state; }
|
||||
inline util::ptr<FileSource> getFileSource() const { return fileSource; }
|
||||
inline util::ptr<Style> getStyle() const { return style; }
|
||||
inline util::ptr<GlyphAtlas> getGlyphAtlas() { return glyphAtlas; }
|
||||
inline GlyphAtlas & getGlyphAtlas() { return glyphAtlas; }
|
||||
inline util::ptr<GlyphStore> getGlyphStore() { return glyphStore; }
|
||||
inline util::ptr<SpriteAtlas> getSpriteAtlas() { return spriteAtlas; }
|
||||
inline SpriteAtlas & getSpriteAtlas() { return spriteAtlas; }
|
||||
util::ptr<Sprite> getSprite();
|
||||
inline util::ptr<Texturepool> getTexturepool() { return texturepool; }
|
||||
inline util::ptr<uv::loop> getLoop() { return loop; }
|
||||
uv::worker &getWorker();
|
||||
inline timestamp getAnimationTime() const { return animationTime; }
|
||||
inline timestamp getTime() const { return animationTime; }
|
||||
@@ -156,22 +151,18 @@ private:
|
||||
void updateSources();
|
||||
void updateSources(const util::ptr<StyleLayerGroup> &group);
|
||||
|
||||
void updateRenderState();
|
||||
|
||||
size_t countLayers(const std::vector<LayerDescription>& layers);
|
||||
|
||||
// Prepares a map render by updating the tiles we need for the current view, as well as updating
|
||||
// the stylesheet.
|
||||
void prepare();
|
||||
|
||||
|
||||
// Unconditionally performs a render with the current map state.
|
||||
void render();
|
||||
void renderLayers(util::ptr<StyleLayerGroup> group);
|
||||
|
||||
private:
|
||||
bool async = false;
|
||||
util::ptr<uv::loop> loop;
|
||||
std::unique_ptr<uv::loop> loop;
|
||||
std::unique_ptr<uv::worker> workers;
|
||||
std::unique_ptr<uv::thread> thread;
|
||||
std::unique_ptr<uv_async_t> async_terminate;
|
||||
@@ -209,9 +200,9 @@ private:
|
||||
util::ptr<FileSource> fileSource;
|
||||
|
||||
util::ptr<Style> style;
|
||||
util::ptr<GlyphAtlas> glyphAtlas;
|
||||
GlyphAtlas glyphAtlas;
|
||||
util::ptr<GlyphStore> glyphStore;
|
||||
util::ptr<SpriteAtlas> spriteAtlas;
|
||||
SpriteAtlas spriteAtlas;
|
||||
util::ptr<Sprite> sprite;
|
||||
util::ptr<Texturepool> texturepool;
|
||||
|
||||
@@ -224,8 +215,6 @@ private:
|
||||
bool debug = false;
|
||||
timestamp animationTime = 0;
|
||||
|
||||
int indent = 0;
|
||||
|
||||
std::set<util::ptr<StyleSource>> activeSources;
|
||||
|
||||
};
|
||||
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
|
||||
virtual void parse();
|
||||
virtual void render(Painter &painter, util::ptr<StyleLayer> layer_desc, const mat4 &matrix);
|
||||
virtual bool hasData(util::ptr<StyleLayer> layer_desc) const;
|
||||
virtual bool hasData(StyleLayer const& layer_desc) const;
|
||||
|
||||
protected:
|
||||
StyleBucketRaster properties;
|
||||
|
||||
@@ -53,11 +53,9 @@ public:
|
||||
}
|
||||
|
||||
// Override this in the child class.
|
||||
virtual void beforeParse();
|
||||
virtual void parse() = 0;
|
||||
virtual void afterParse();
|
||||
virtual void render(Painter &painter, util::ptr<StyleLayer> layer_desc, const mat4 &matrix) = 0;
|
||||
virtual bool hasData(util::ptr<StyleLayer> layer_desc) const = 0;
|
||||
virtual bool hasData(StyleLayer const& layer_desc) const = 0;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <mbgl/style/filter_expression.hpp>
|
||||
#include <mbgl/text/glyph.hpp>
|
||||
#include <mbgl/util/ptr.hpp>
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <cstdint>
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
@@ -29,13 +29,14 @@ class StyleLayerGroup;
|
||||
class VectorTileData;
|
||||
class Collision;
|
||||
|
||||
class TileParser {
|
||||
class TileParser : private util::noncopyable
|
||||
{
|
||||
public:
|
||||
TileParser(const std::string &data, VectorTileData &tile,
|
||||
const util::ptr<const Style> &style,
|
||||
const util::ptr<GlyphAtlas> &glyphAtlas,
|
||||
GlyphAtlas & glyphAtlas,
|
||||
const util::ptr<GlyphStore> &glyphStore,
|
||||
const util::ptr<SpriteAtlas> &spriteAtlas,
|
||||
SpriteAtlas & spriteAtlas,
|
||||
const util::ptr<Sprite> &sprite);
|
||||
~TileParser();
|
||||
|
||||
@@ -60,9 +61,9 @@ private:
|
||||
|
||||
// Cross-thread shared data.
|
||||
util::ptr<const Style> style;
|
||||
util::ptr<GlyphAtlas> glyphAtlas;
|
||||
GlyphAtlas & glyphAtlas;
|
||||
util::ptr<GlyphStore> glyphStore;
|
||||
util::ptr<SpriteAtlas> spriteAtlas;
|
||||
SpriteAtlas & spriteAtlas;
|
||||
util::ptr<Sprite> sprite;
|
||||
util::ptr<Texturepool> texturePool;
|
||||
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
|
||||
#include <mbgl/util/time.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/uv.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cmath>
|
||||
#include <forward_list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
@@ -80,7 +78,7 @@ private:
|
||||
private:
|
||||
View &view;
|
||||
|
||||
std::unique_ptr<uv::rwlock> mtx;
|
||||
mutable std::recursive_mutex mtx;
|
||||
|
||||
// This reflects the current state of the transform, representing the actual position of the
|
||||
// map. After calling a transform function with a timer, this will likely remain the same until
|
||||
@@ -91,7 +89,6 @@ private:
|
||||
TransformState final;
|
||||
|
||||
// Limit the amount of zooming possible on the map.
|
||||
// TODO: make these modifiable from outside.
|
||||
const double min_scale = std::pow(2, 0);
|
||||
const double max_scale = std::pow(2, 18);
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ public:
|
||||
float lngX(float lon) const;
|
||||
float latY(float lat) const;
|
||||
std::array<float, 2> locationCoordinate(float lon, float lat) const;
|
||||
void getLonLat(double &lon, double &lat) const;
|
||||
|
||||
// Zoom
|
||||
float getNormalizedZoom() const;
|
||||
@@ -69,7 +70,7 @@ private:
|
||||
// map position
|
||||
double x = 0, y = 0;
|
||||
double angle = 0;
|
||||
double scale = std::numeric_limits<double>::infinity();
|
||||
double scale = 1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -28,12 +28,9 @@ class VectorTileData : public TileData {
|
||||
public:
|
||||
VectorTileData(Tile::ID id, Map &map, const util::ptr<SourceInfo> &source);
|
||||
~VectorTileData();
|
||||
|
||||
virtual void beforeParse();
|
||||
virtual void parse();
|
||||
virtual void afterParse();
|
||||
virtual void render(Painter &painter, util::ptr<StyleLayer> layer_desc, const mat4 &matrix);
|
||||
virtual bool hasData(util::ptr<StyleLayer> layer_desc) const;
|
||||
virtual bool hasData(StyleLayer const& layer_desc) const;
|
||||
|
||||
protected:
|
||||
// Holds the actual geometries in this tile.
|
||||
@@ -49,9 +46,6 @@ protected:
|
||||
// Holds the buckets of this tile.
|
||||
// They contain the location offsets in the buffers stored above
|
||||
std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
|
||||
|
||||
std::unique_ptr<TileParser> parser;
|
||||
|
||||
public:
|
||||
const float depth;
|
||||
};
|
||||
|
||||
@@ -35,9 +35,12 @@ enum class RenderPass : bool { Opaque, Translucent };
|
||||
class Transform;
|
||||
class Style;
|
||||
class Tile;
|
||||
class Sprite;
|
||||
class SpriteAtlas;
|
||||
class GlyphAtlas;
|
||||
class Source;
|
||||
class StyleSource;
|
||||
class StyleLayerGroup;
|
||||
|
||||
class FillBucket;
|
||||
class LineBucket;
|
||||
@@ -53,10 +56,9 @@ class RasterTileData;
|
||||
|
||||
class Painter : private util::noncopyable {
|
||||
public:
|
||||
Painter(Map &map);
|
||||
Painter(SpriteAtlas&, GlyphAtlas&);
|
||||
~Painter();
|
||||
|
||||
|
||||
void setup();
|
||||
|
||||
// Perform cleanup tasks that prepare shutting down the app. This doesn't mean that the
|
||||
@@ -73,6 +75,14 @@ public:
|
||||
// Updates the default matrices to the current viewport dimensions.
|
||||
void changeMatrix();
|
||||
|
||||
void render(const Style& style,
|
||||
const std::set<util::ptr<StyleSource>>& sources,
|
||||
TransformState state,
|
||||
timestamp time);
|
||||
|
||||
void renderLayers(util::ptr<StyleLayerGroup> group);
|
||||
void renderLayer(util::ptr<StyleLayer> layer_desc, const Tile::ID* id = nullptr, const mat4* matrix = nullptr);
|
||||
|
||||
// Renders a particular layer from a tile.
|
||||
void renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc, const mat4 &matrix);
|
||||
|
||||
@@ -167,9 +177,10 @@ public:
|
||||
}();
|
||||
|
||||
private:
|
||||
Map& map;
|
||||
TransformState state;
|
||||
|
||||
bool debug = false;
|
||||
int indent = 0;
|
||||
|
||||
uint32_t gl_program = 0;
|
||||
float gl_lineWidth = 0;
|
||||
@@ -183,6 +194,9 @@ private:
|
||||
public:
|
||||
FrameHistory frameHistory;
|
||||
|
||||
SpriteAtlas& spriteAtlas;
|
||||
GlyphAtlas& glyphAtlas;
|
||||
|
||||
std::unique_ptr<PlainShader> plainShader;
|
||||
std::unique_ptr<OutlineShader> outlineShader;
|
||||
std::unique_ptr<LineShader> lineShader;
|
||||
|
||||
@@ -24,7 +24,7 @@ SpriteAtlas::SpriteAtlas(dimension width_, dimension height_)
|
||||
bool SpriteAtlas::resize(const float newRatio) {
|
||||
if (pixelRatio == newRatio) return false;
|
||||
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
const float oldRatio = pixelRatio;
|
||||
pixelRatio = newRatio;
|
||||
@@ -104,15 +104,15 @@ Rect<SpriteAtlas::dimension> SpriteAtlas::allocateImage(size_t pixel_width, size
|
||||
return rect;
|
||||
}
|
||||
|
||||
Rect<SpriteAtlas::dimension> SpriteAtlas::getImage(const std::string &name, const Sprite &sprite) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
Rect<SpriteAtlas::dimension> SpriteAtlas::getImage(const std::string& name) {
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
auto rect_it = images.find(name);
|
||||
if (rect_it != images.end()) {
|
||||
return rect_it->second;
|
||||
}
|
||||
|
||||
const SpritePosition &pos = sprite.getSpritePosition(name);
|
||||
const SpritePosition &pos = sprite->getSpritePosition(name);
|
||||
if (!pos.width || !pos.height) {
|
||||
return Rect<dimension> { 0, 0, 0, 0 };
|
||||
}
|
||||
@@ -127,16 +127,17 @@ Rect<SpriteAtlas::dimension> SpriteAtlas::getImage(const std::string &name, cons
|
||||
|
||||
images.emplace(name, rect);
|
||||
|
||||
copy(rect, pos, sprite);
|
||||
copy(rect, pos);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
SpriteAtlasPosition SpriteAtlas::getPosition(const std::string& name, const Sprite& sprite, bool repeating) {
|
||||
SpriteAtlasPosition SpriteAtlas::getPosition(const std::string& name, bool repeating) {
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
// `repeating` indicates that the image will be used in a repeating pattern
|
||||
// repeating pattern images are assumed to have a 1px padding that mirrors the opposite edge
|
||||
// positions for repeating images are adjusted to exclude the edge
|
||||
Rect<dimension> rect = getImage(name, sprite);
|
||||
Rect<dimension> rect = getImage(name);
|
||||
const int r = repeating ? 1 : 0;
|
||||
return SpriteAtlasPosition {
|
||||
{{ float(rect.w) / pixelRatio, float(rect.h) / pixelRatio }},
|
||||
@@ -145,11 +146,6 @@ SpriteAtlasPosition SpriteAtlas::getPosition(const std::string& name, const Spri
|
||||
};
|
||||
}
|
||||
|
||||
Rect<SpriteAtlas::dimension> SpriteAtlas::waitForImage(const std::string &name, const Sprite &sprite) {
|
||||
sprite.waitUntilLoaded();
|
||||
return getImage(name, sprite);
|
||||
}
|
||||
|
||||
void SpriteAtlas::allocate() {
|
||||
if (!data) {
|
||||
dimension w = static_cast<dimension>(width * pixelRatio);
|
||||
@@ -159,15 +155,15 @@ void SpriteAtlas::allocate() {
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteAtlas::copy(const Rect<dimension> &dst, const SpritePosition &src, const Sprite &sprite) {
|
||||
if (!sprite.raster) return;
|
||||
const uint32_t *src_img = reinterpret_cast<const uint32_t *>(sprite.raster->getData());
|
||||
void SpriteAtlas::copy(const Rect<dimension>& dst, const SpritePosition& src) {
|
||||
if (!sprite->raster) return;
|
||||
const uint32_t *src_img = reinterpret_cast<const uint32_t *>(sprite->raster->getData());
|
||||
allocate();
|
||||
uint32_t *dst_img = reinterpret_cast<uint32_t *>(data);
|
||||
|
||||
copy_bitmap(
|
||||
/* source buffer */ src_img,
|
||||
/* source stride */ sprite.raster->getWidth(),
|
||||
/* source stride */ sprite->raster->getWidth(),
|
||||
/* source x */ src.x,
|
||||
/* source y */ src.y,
|
||||
/* dest buffer */ dst_img,
|
||||
@@ -181,14 +177,16 @@ void SpriteAtlas::copy(const Rect<dimension> &dst, const SpritePosition &src, co
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void SpriteAtlas::setSprite(util::ptr<Sprite> sprite_) {
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
void SpriteAtlas::update(const Sprite &sprite) {
|
||||
if (!sprite.isLoaded()) return;
|
||||
sprite = sprite_;
|
||||
|
||||
SpriteAtlas &atlas = *this;
|
||||
util::erase_if(uninitialized, [&sprite, &atlas](const std::string &name) {
|
||||
Rect<dimension> dst = atlas.getImage(name, sprite);
|
||||
const SpritePosition &src = sprite.getSpritePosition(name);
|
||||
if (!sprite->isLoaded()) return;
|
||||
|
||||
util::erase_if(uninitialized, [this](const std::string &name) {
|
||||
Rect<dimension> dst = getImage(name);
|
||||
const SpritePosition& src = sprite->getSpritePosition(name);
|
||||
if (!src) {
|
||||
if (debug::spriteWarnings) {
|
||||
fprintf(stderr, "[WARNING] sprite doesn't have image with name '%s'\n", name.c_str());
|
||||
@@ -196,8 +194,8 @@ void SpriteAtlas::update(const Sprite &sprite) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (src.width == dst.w * atlas.pixelRatio && src.height == dst.h * atlas.pixelRatio && src.pixelRatio == atlas.pixelRatio) {
|
||||
atlas.copy(dst, src, sprite);
|
||||
if (src.width == dst.w * pixelRatio && src.height == dst.h * pixelRatio && src.pixelRatio == pixelRatio) {
|
||||
copy(dst, src);
|
||||
return true;
|
||||
} else {
|
||||
if (debug::spriteWarnings) {
|
||||
@@ -228,7 +226,7 @@ void SpriteAtlas::bind(bool linear) {
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
allocate();
|
||||
|
||||
if (first) {
|
||||
@@ -257,15 +255,12 @@ void SpriteAtlas::bind(bool linear) {
|
||||
);
|
||||
}
|
||||
|
||||
#if defined(DEBUG)
|
||||
// platform::show_color_debug_image("Sprite Atlas", reinterpret_cast<char *>(data), width, height, width * pixelRatio, height * pixelRatio);
|
||||
#endif
|
||||
dirty = false;
|
||||
}
|
||||
};
|
||||
|
||||
SpriteAtlas::~SpriteAtlas() {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
glDeleteTextures(1, &texture);
|
||||
texture = 0;
|
||||
|
||||
170
src/map/map.cpp
170
src/map/map.cpp
@@ -31,7 +31,7 @@
|
||||
using namespace mbgl;
|
||||
|
||||
Map::Map(View& view_)
|
||||
: loop(std::make_shared<uv::loop>()),
|
||||
: loop(std::make_unique<uv::loop>()),
|
||||
thread(std::make_unique<uv::thread>()),
|
||||
async_terminate(new uv_async_t()),
|
||||
async_render(new uv_async_t()),
|
||||
@@ -41,13 +41,12 @@ Map::Map(View& view_)
|
||||
main_thread(uv_thread_self()),
|
||||
#endif
|
||||
transform(view_),
|
||||
glyphAtlas(std::make_shared<GlyphAtlas>(1024, 1024)),
|
||||
spriteAtlas(std::make_shared<SpriteAtlas>(512, 512)),
|
||||
glyphAtlas(1024, 1024),
|
||||
spriteAtlas(512, 512),
|
||||
texturepool(std::make_shared<Texturepool>()),
|
||||
painter(*this) {
|
||||
|
||||
painter(spriteAtlas, glyphAtlas)
|
||||
{
|
||||
view.initialize(this);
|
||||
|
||||
// Make sure that we're doing an initial drawing in all cases.
|
||||
is_clean.clear();
|
||||
is_rendered.clear();
|
||||
@@ -62,9 +61,7 @@ Map::~Map() {
|
||||
// Explicitly reset all pointers.
|
||||
texturepool.reset();
|
||||
sprite.reset();
|
||||
spriteAtlas.reset();
|
||||
glyphStore.reset();
|
||||
glyphAtlas.reset();
|
||||
style.reset();
|
||||
fileSource.reset();
|
||||
workers.reset();
|
||||
@@ -598,15 +595,6 @@ void Map::updateTiles() {
|
||||
}
|
||||
}
|
||||
|
||||
void Map::updateRenderState() {
|
||||
// Update all clipping IDs.
|
||||
ClipIDGenerator generator;
|
||||
for (const util::ptr<StyleSource> &source : getActiveSources()) {
|
||||
generator.update(source->source->getLoadedTiles());
|
||||
source->source->updateMatrices(painter.projMatrix, state);
|
||||
}
|
||||
}
|
||||
|
||||
void Map::prepare() {
|
||||
if (!fileSource) {
|
||||
fileSource = std::make_shared<FileSource>(**loop, platform::defaultCacheDatabase());
|
||||
@@ -645,8 +633,8 @@ void Map::prepare() {
|
||||
style->updateProperties(state.getNormalizedZoom(), animationTime);
|
||||
|
||||
// Allow the sprite atlas to potentially pull new sprite images if needed.
|
||||
spriteAtlas->resize(state.getPixelRatio());
|
||||
spriteAtlas->update(*getSprite());
|
||||
spriteAtlas.resize(state.getPixelRatio());
|
||||
spriteAtlas.setSprite(getSprite());
|
||||
|
||||
updateTiles();
|
||||
}
|
||||
@@ -654,152 +642,12 @@ void Map::prepare() {
|
||||
void Map::render() {
|
||||
view.make_active();
|
||||
|
||||
painter.clear();
|
||||
|
||||
painter.resize();
|
||||
|
||||
painter.changeMatrix();
|
||||
|
||||
updateRenderState();
|
||||
|
||||
painter.drawClippingMasks(getActiveSources());
|
||||
|
||||
painter.frameHistory.record(getAnimationTime(), getState().getNormalizedZoom());
|
||||
|
||||
// Actually render the layers
|
||||
if (debug::renderTree) { std::cout << "{" << std::endl; indent++; }
|
||||
renderLayers(style->layers);
|
||||
if (debug::renderTree) { std::cout << "}" << std::endl; indent--; }
|
||||
|
||||
// Finalize the rendering, e.g. by calling debug render calls per tile.
|
||||
// This guarantees that we have at least one function per tile called.
|
||||
// When only rendering layers via the stylesheet, it's possible that we don't
|
||||
// ever visit a tile during rendering.
|
||||
for (const util::ptr<StyleSource> &source : getActiveSources()) {
|
||||
source->source->finishRender(painter);
|
||||
}
|
||||
|
||||
painter.render(*style, activeSources,
|
||||
state, animationTime);
|
||||
// Schedule another rerender when we definitely need a next frame.
|
||||
if (transform.needsTransition() || style->hasTransitions()) {
|
||||
update();
|
||||
}
|
||||
|
||||
glFlush();
|
||||
|
||||
view.make_inactive();
|
||||
}
|
||||
|
||||
void Map::renderLayers(util::ptr<StyleLayerGroup> group) {
|
||||
if (!group) {
|
||||
// Make sure that we actually do have a layer group.
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Correctly compute the number of layers recursively beforehand.
|
||||
float strata_thickness = 1.0f / (group->layers.size() + 1);
|
||||
|
||||
// - FIRST PASS ------------------------------------------------------------
|
||||
// Render everything top-to-bottom by using reverse iterators. Render opaque
|
||||
// objects first.
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent++ * 4, ' ') << "OPAQUE {" << std::endl;
|
||||
}
|
||||
int i = 0;
|
||||
for (auto it = group->layers.rbegin(), end = group->layers.rend(); it != end; ++it, ++i) {
|
||||
painter.setOpaque();
|
||||
painter.setStrata(i * strata_thickness);
|
||||
renderLayer(*it, RenderPass::Opaque);
|
||||
}
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
|
||||
}
|
||||
|
||||
// - SECOND PASS -----------------------------------------------------------
|
||||
// Make a second pass, rendering translucent objects. This time, we render
|
||||
// bottom-to-top.
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent++ * 4, ' ') << "TRANSLUCENT {" << std::endl;
|
||||
}
|
||||
--i;
|
||||
for (auto it = group->layers.begin(), end = group->layers.end(); it != end; ++it, --i) {
|
||||
painter.setTranslucent();
|
||||
painter.setStrata(i * strata_thickness);
|
||||
renderLayer(*it, RenderPass::Translucent);
|
||||
}
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Map::renderLayer(util::ptr<StyleLayer> layer_desc, RenderPass pass, const Tile::ID* id, const mat4* matrix) {
|
||||
if (layer_desc->type == StyleLayerType::Background) {
|
||||
// This layer defines a background color/image.
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
|
||||
<< layer_desc->type << ")" << std::endl;
|
||||
}
|
||||
|
||||
painter.renderBackground(layer_desc);
|
||||
} else {
|
||||
// This is a singular layer.
|
||||
if (!layer_desc->bucket) {
|
||||
fprintf(stderr, "[WARNING] layer '%s' is missing bucket\n", layer_desc->id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!layer_desc->bucket->style_source) {
|
||||
fprintf(stderr, "[WARNING] can't find source for layer '%s'\n", layer_desc->id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
StyleSource &style_source = *layer_desc->bucket->style_source;
|
||||
|
||||
// Skip this layer if there is no data.
|
||||
if (!style_source.source) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip this layer if it's outside the range of min/maxzoom.
|
||||
// This may occur when there /is/ a bucket created for this layer, but the min/max-zoom
|
||||
// is set to a fractional value, or value that is larger than the source maxzoom.
|
||||
const double zoom = state.getZoom();
|
||||
if (layer_desc->bucket->min_zoom > zoom ||
|
||||
layer_desc->bucket->max_zoom <= zoom) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Abort early if we can already deduce from the bucket type that
|
||||
// we're not going to render anything anyway during this pass.
|
||||
switch (layer_desc->type) {
|
||||
case StyleLayerType::Fill:
|
||||
if (!layer_desc->getProperties<FillProperties>().isVisible()) return;
|
||||
break;
|
||||
case StyleLayerType::Line:
|
||||
if (pass == RenderPass::Opaque) return;
|
||||
if (!layer_desc->getProperties<LineProperties>().isVisible()) return;
|
||||
break;
|
||||
case StyleLayerType::Symbol:
|
||||
if (pass == RenderPass::Opaque) return;
|
||||
if (!layer_desc->getProperties<SymbolProperties>().isVisible()) return;
|
||||
break;
|
||||
case StyleLayerType::Raster:
|
||||
if (pass == RenderPass::Opaque) return;
|
||||
if (!layer_desc->getProperties<RasterProperties>().isVisible()) return;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
|
||||
<< layer_desc->type << ")" << std::endl;
|
||||
}
|
||||
if (!id) {
|
||||
style_source.source->render(painter, layer_desc);
|
||||
} else {
|
||||
style_source.source->render(painter, layer_desc, *id, *matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,6 @@ void RasterTileData::render(Painter &painter, util::ptr<StyleLayer> layer_desc,
|
||||
bucket.render(painter, layer_desc, id, matrix);
|
||||
}
|
||||
|
||||
bool RasterTileData::hasData(util::ptr<StyleLayer> /*layer_desc*/) const {
|
||||
bool RasterTileData::hasData(StyleLayer const& /*layer_desc*/) const {
|
||||
return bucket.hasData();
|
||||
}
|
||||
|
||||
@@ -79,11 +79,8 @@ void TileData::cancel() {
|
||||
}
|
||||
}
|
||||
|
||||
void TileData::beforeParse() {}
|
||||
|
||||
void TileData::reparse() {
|
||||
beforeParse();
|
||||
|
||||
void TileData::reparse()
|
||||
{
|
||||
// We're creating a new work request. The work request deletes itself after it executed
|
||||
// the after work handler
|
||||
new uv::work<util::ptr<TileData>>(
|
||||
@@ -92,10 +89,7 @@ void TileData::reparse() {
|
||||
tile->parse();
|
||||
},
|
||||
[](util::ptr<TileData> &tile) {
|
||||
tile->afterParse();
|
||||
tile->map.update();
|
||||
},
|
||||
shared_from_this());
|
||||
}
|
||||
|
||||
void TileData::afterParse() {}
|
||||
|
||||
@@ -39,9 +39,9 @@ TileParser::~TileParser() = default;
|
||||
|
||||
TileParser::TileParser(const std::string &data, VectorTileData &tile_,
|
||||
const util::ptr<const Style> &style_,
|
||||
const util::ptr<GlyphAtlas> &glyphAtlas_,
|
||||
GlyphAtlas & glyphAtlas_,
|
||||
const util::ptr<GlyphStore> &glyphStore_,
|
||||
const util::ptr<SpriteAtlas> &spriteAtlas_,
|
||||
SpriteAtlas & spriteAtlas_,
|
||||
const util::ptr<Sprite> &sprite_)
|
||||
: vector_data(pbf((const uint8_t *)data.data(), data.size())),
|
||||
tile(tile_),
|
||||
@@ -53,9 +53,7 @@ TileParser::TileParser(const std::string &data, VectorTileData &tile_,
|
||||
collision(std::make_unique<Collision>(tile.id.z, 4096, tile.source->tile_size, tile.depth)) {
|
||||
assert(&tile != nullptr);
|
||||
assert(style);
|
||||
assert(glyphAtlas);
|
||||
assert(glyphStore);
|
||||
assert(spriteAtlas);
|
||||
assert(sprite);
|
||||
assert(collision);
|
||||
}
|
||||
@@ -177,7 +175,7 @@ std::unique_ptr<Bucket> TileParser::createLineBucket(const VectorTileLayer& laye
|
||||
|
||||
std::unique_ptr<Bucket> TileParser::createSymbolBucket(const VectorTileLayer& layer, const FilterExpression &filter, const StyleBucketSymbol &symbol) {
|
||||
std::unique_ptr<SymbolBucket> bucket = std::make_unique<SymbolBucket>(symbol, *collision);
|
||||
bucket->addFeatures(layer, filter, tile.id, *spriteAtlas, *sprite, *glyphAtlas, *glyphStore);
|
||||
bucket->addFeatures(layer, filter, tile.id, spriteAtlas, *sprite, glyphAtlas, *glyphStore);
|
||||
return obsolete() ? nullptr : std::move(bucket);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,28 +5,27 @@
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/math.hpp>
|
||||
#include <mbgl/util/time.hpp>
|
||||
#include <mbgl/util/uv_detail.hpp>
|
||||
#include <mbgl/util/transition.hpp>
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
const double D2R = M_PI / 180.0;
|
||||
const double R2D = 180.0 / M_PI;
|
||||
const double M2PI = 2 * M_PI;
|
||||
const double MIN_ROTATE_SCALE = 8;
|
||||
|
||||
Transform::Transform(View &view_) : view(view_), mtx(std::make_unique<uv::rwlock>()) {
|
||||
setScale(current.scale);
|
||||
setAngle(current.angle);
|
||||
Transform::Transform(View &view_)
|
||||
: view(view_)
|
||||
{
|
||||
}
|
||||
|
||||
#pragma mark - Map View
|
||||
|
||||
bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
|
||||
const uint16_t fb_w, const uint16_t fb_h) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
if (final.width != w || final.height != h || final.pixelRatio != ratio ||
|
||||
final.framebuffer[0] != fb_w || final.framebuffer[1] != fb_h) {
|
||||
@@ -52,7 +51,7 @@ bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
|
||||
#pragma mark - Position
|
||||
|
||||
void Transform::moveBy(const double dx, const double dy, const timestamp duration) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
_moveBy(dx, dy, duration);
|
||||
}
|
||||
@@ -94,7 +93,7 @@ void Transform::_moveBy(const double dx, const double dy, const timestamp durati
|
||||
}
|
||||
|
||||
void Transform::setLonLat(const double lon, const double lat, const timestamp duration) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
const double f = std::fmin(std::fmax(std::sin(D2R * lat), -0.9999), 0.9999);
|
||||
double xn = -lon * Bc;
|
||||
@@ -105,7 +104,7 @@ void Transform::setLonLat(const double lon, const double lat, const timestamp du
|
||||
|
||||
void Transform::setLonLatZoom(const double lon, const double lat, const double zoom,
|
||||
const timestamp duration) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
double new_scale = std::pow(2.0, zoom);
|
||||
|
||||
@@ -121,21 +120,20 @@ void Transform::setLonLatZoom(const double lon, const double lat, const double z
|
||||
}
|
||||
|
||||
void Transform::getLonLat(double &lon, double &lat) const {
|
||||
uv::readlock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
lon = -final.x / Bc;
|
||||
lat = R2D * (2 * std::atan(std::exp(final.y / Cc)) - 0.5 * M_PI);
|
||||
final.getLonLat(lon, lat);
|
||||
}
|
||||
|
||||
void Transform::getLonLatZoom(double &lon, double &lat, double &zoom) const {
|
||||
getLonLat(lon, lat);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
uv::readlock lock(mtx);
|
||||
getLonLat(lon, lat);
|
||||
zoom = getZoom();
|
||||
}
|
||||
|
||||
void Transform::startPanning() {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
_clearPanning();
|
||||
|
||||
@@ -147,7 +145,7 @@ void Transform::startPanning() {
|
||||
}
|
||||
|
||||
void Transform::stopPanning() {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
_clearPanning();
|
||||
}
|
||||
@@ -163,7 +161,7 @@ void Transform::_clearPanning() {
|
||||
#pragma mark - Zoom
|
||||
|
||||
void Transform::scaleBy(const double ds, const double cx, const double cy, const timestamp duration) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
// clamp scale to min/max values
|
||||
double new_scale = current.scale * ds;
|
||||
@@ -178,31 +176,31 @@ void Transform::scaleBy(const double ds, const double cx, const double cy, const
|
||||
|
||||
void Transform::setScale(const double scale, const double cx, const double cy,
|
||||
const timestamp duration) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
_setScale(scale, cx, cy, duration);
|
||||
}
|
||||
|
||||
void Transform::setZoom(const double zoom, const timestamp duration) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
_setScale(std::pow(2.0, zoom), -1, -1, duration);
|
||||
}
|
||||
|
||||
double Transform::getZoom() const {
|
||||
uv::readlock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
return std::log(final.scale) / M_LN2;
|
||||
}
|
||||
|
||||
double Transform::getScale() const {
|
||||
uv::readlock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
return final.scale;
|
||||
}
|
||||
|
||||
void Transform::startScaling() {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
_clearScaling();
|
||||
|
||||
@@ -214,7 +212,7 @@ void Transform::startScaling() {
|
||||
}
|
||||
|
||||
void Transform::stopScaling() {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
_clearScaling();
|
||||
}
|
||||
@@ -333,7 +331,7 @@ void Transform::constrain(double& scale, double& y) const {
|
||||
|
||||
void Transform::rotateBy(const double start_x, const double start_y, const double end_x,
|
||||
const double end_y, const timestamp duration) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
double center_x = current.width / 2, center_y = current.height / 2;
|
||||
|
||||
@@ -363,13 +361,13 @@ void Transform::rotateBy(const double start_x, const double start_y, const doubl
|
||||
}
|
||||
|
||||
void Transform::setAngle(const double new_angle, const timestamp duration) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
_setAngle(new_angle, duration);
|
||||
}
|
||||
|
||||
void Transform::setAngle(const double new_angle, const double cx, const double cy) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
double dx = 0, dy = 0;
|
||||
|
||||
@@ -418,13 +416,13 @@ void Transform::_setAngle(double new_angle, const timestamp duration) {
|
||||
}
|
||||
|
||||
double Transform::getAngle() const {
|
||||
uv::readlock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
return final.angle;
|
||||
}
|
||||
|
||||
void Transform::startRotating() {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
_clearRotating();
|
||||
|
||||
@@ -436,7 +434,7 @@ void Transform::startRotating() {
|
||||
}
|
||||
|
||||
void Transform::stopRotating() {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
_clearRotating();
|
||||
}
|
||||
@@ -458,13 +456,13 @@ bool Transform::canRotate() {
|
||||
#pragma mark - Transition
|
||||
|
||||
bool Transform::needsTransition() const {
|
||||
uv::readlock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
return !transitions.empty();
|
||||
}
|
||||
|
||||
void Transform::updateTransitions(const timestamp now) {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
transitions.remove_if([now](const util::ptr<util::transition> &transition) {
|
||||
return transition->update(now) == util::transition::complete;
|
||||
@@ -472,7 +470,7 @@ void Transform::updateTransitions(const timestamp now) {
|
||||
}
|
||||
|
||||
void Transform::cancelTransitions() {
|
||||
uv::writelock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
transitions.clear();
|
||||
}
|
||||
@@ -480,13 +478,13 @@ void Transform::cancelTransitions() {
|
||||
#pragma mark - Transform state
|
||||
|
||||
const TransformState Transform::currentState() const {
|
||||
uv::readlock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
const TransformState Transform::finalState() const {
|
||||
uv::readlock lock(mtx);
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
return final;
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
const double R2D = 180.0 / M_PI;
|
||||
|
||||
#pragma mark - Matrix
|
||||
|
||||
void TransformState::matrixFor(mat4& matrix, const Tile::ID& id) const {
|
||||
@@ -108,6 +110,15 @@ std::array<float, 2> TransformState::locationCoordinate(float lon, float lat) co
|
||||
}};
|
||||
}
|
||||
|
||||
void TransformState::getLonLat(double &lon, double &lat) const {
|
||||
const double s = scale * util::tileSize;
|
||||
const double Bc = s / 360;
|
||||
const double Cc = s / (2 * M_PI);
|
||||
|
||||
lon = -x / Bc;
|
||||
lat = R2D * (2 * std::atan(std::exp(y / Cc)) - 0.5 * M_PI);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Zoom
|
||||
|
||||
|
||||
@@ -14,16 +14,9 @@ VectorTileData::VectorTileData(Tile::ID id_, Map &map_, const util::ptr<SourceIn
|
||||
}
|
||||
|
||||
VectorTileData::~VectorTileData() {
|
||||
util::ptr<GlyphAtlas> glyphAtlas = map.getGlyphAtlas();
|
||||
if (glyphAtlas) {
|
||||
glyphAtlas->removeGlyphs(id.to_uint64());
|
||||
}
|
||||
map.getGlyphAtlas().removeGlyphs(id.to_uint64());
|
||||
}
|
||||
|
||||
void VectorTileData::beforeParse() {
|
||||
|
||||
parser = std::make_unique<TileParser>(data, *this, map.getStyle(), map.getGlyphAtlas(), map.getGlyphStore(), map.getSpriteAtlas(), map.getSprite());
|
||||
}
|
||||
|
||||
void VectorTileData::parse() {
|
||||
if (state != State::loaded) {
|
||||
@@ -34,7 +27,9 @@ void VectorTileData::parse() {
|
||||
// Parsing creates state that is encapsulated in TileParser. While parsing,
|
||||
// the TileParser object writes results into this objects. All other state
|
||||
// is going to be discarded afterwards.
|
||||
parser->parse();
|
||||
TileParser parser(data, *this, map.getStyle(), map.getGlyphAtlas(),
|
||||
map.getGlyphStore(), map.getSpriteAtlas(), map.getSprite());
|
||||
parser.parse();
|
||||
} catch (const std::exception& ex) {
|
||||
#if defined(DEBUG)
|
||||
fprintf(stderr, "[%p] exception [%d/%d/%d]... failed: %s\n", this, id.z, id.x, id.y, ex.what());
|
||||
@@ -48,10 +43,6 @@ void VectorTileData::parse() {
|
||||
}
|
||||
}
|
||||
|
||||
void VectorTileData::afterParse() {
|
||||
parser.reset();
|
||||
}
|
||||
|
||||
void VectorTileData::render(Painter &painter, util::ptr<StyleLayer> layer_desc, const mat4 &matrix) {
|
||||
if (state == State::parsed && layer_desc->bucket) {
|
||||
auto databucket_it = buckets.find(layer_desc->bucket->name);
|
||||
@@ -62,9 +53,9 @@ void VectorTileData::render(Painter &painter, util::ptr<StyleLayer> layer_desc,
|
||||
}
|
||||
}
|
||||
|
||||
bool VectorTileData::hasData(util::ptr<StyleLayer> layer_desc) const {
|
||||
if (state == State::parsed && layer_desc->bucket) {
|
||||
auto databucket_it = buckets.find(layer_desc->bucket->name);
|
||||
bool VectorTileData::hasData(StyleLayer const& layer_desc) const {
|
||||
if (state == State::parsed && layer_desc.bucket) {
|
||||
auto databucket_it = buckets.find(layer_desc.bucket->name);
|
||||
if (databucket_it != buckets.end()) {
|
||||
assert(databucket_it->second);
|
||||
return databucket_it->second->hasData();
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/style/style.hpp>
|
||||
#include <mbgl/style/style_layer.hpp>
|
||||
#include <mbgl/style/style_layer_group.hpp>
|
||||
#include <mbgl/style/style_bucket.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
#include <mbgl/util/time.hpp>
|
||||
@@ -9,6 +10,7 @@
|
||||
#include <mbgl/util/constants.hpp>
|
||||
#include <mbgl/util/mat3.hpp>
|
||||
#include <mbgl/geometry/sprite_atlas.hpp>
|
||||
#include <mbgl/map/source.hpp>
|
||||
|
||||
#if defined(DEBUG)
|
||||
#include <mbgl/util/stopwatch.hpp>
|
||||
@@ -16,13 +18,16 @@
|
||||
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
|
||||
|
||||
Painter::Painter(Map &map_)
|
||||
: map(map_) {
|
||||
Painter::Painter(SpriteAtlas& spriteAtlas_, GlyphAtlas& glyphAtlas_)
|
||||
: spriteAtlas(spriteAtlas_)
|
||||
, glyphAtlas(glyphAtlas_)
|
||||
{
|
||||
}
|
||||
|
||||
Painter::~Painter() {
|
||||
@@ -109,7 +114,6 @@ void Painter::terminate() {
|
||||
}
|
||||
|
||||
void Painter::resize() {
|
||||
const TransformState &state = map.getState();
|
||||
if (gl_viewport != state.getFramebufferDimensions()) {
|
||||
gl_viewport = state.getFramebufferDimensions();
|
||||
assert(gl_viewport[0] > 0 && gl_viewport[1] > 0);
|
||||
@@ -152,12 +156,12 @@ void Painter::depthRange(const float near, const float far) {
|
||||
|
||||
void Painter::changeMatrix() {
|
||||
// Initialize projection matrix
|
||||
matrix::ortho(projMatrix, 0, map.getState().getWidth(), map.getState().getHeight(), 0, 0, 1);
|
||||
matrix::ortho(projMatrix, 0, state.getWidth(), state.getHeight(), 0, 0, 1);
|
||||
|
||||
// The extrusion matrix.
|
||||
matrix::identity(extrudeMatrix);
|
||||
matrix::multiply(extrudeMatrix, projMatrix, extrudeMatrix);
|
||||
matrix::rotate_z(extrudeMatrix, extrudeMatrix, map.getState().getAngle());
|
||||
matrix::rotate_z(extrudeMatrix, extrudeMatrix, state.getAngle());
|
||||
|
||||
// The native matrix is a 1:1 matrix that paints the coordinates at the
|
||||
// same screen position as the vertex specifies.
|
||||
@@ -200,9 +204,159 @@ void Painter::prepareTile(const Tile& tile) {
|
||||
glStencilFunc(GL_EQUAL, ref, mask);
|
||||
}
|
||||
|
||||
void Painter::render(const Style& style, const std::set<util::ptr<StyleSource>>& sources,
|
||||
TransformState state_, timestamp time) {
|
||||
state = state_;
|
||||
|
||||
clear();
|
||||
resize();
|
||||
changeMatrix();
|
||||
|
||||
// Update all clipping IDs.
|
||||
ClipIDGenerator generator;
|
||||
for (const util::ptr<StyleSource> &source : sources) {
|
||||
generator.update(source->source->getLoadedTiles());
|
||||
source->source->updateMatrices(projMatrix, state);
|
||||
}
|
||||
|
||||
drawClippingMasks(sources);
|
||||
|
||||
frameHistory.record(time, state.getNormalizedZoom());
|
||||
|
||||
// Actually render the layers
|
||||
if (debug::renderTree) { std::cout << "{" << std::endl; indent++; }
|
||||
renderLayers(style.layers);
|
||||
if (debug::renderTree) { std::cout << "}" << std::endl; indent--; }
|
||||
|
||||
// Finalize the rendering, e.g. by calling debug render calls per tile.
|
||||
// This guarantees that we have at least one function per tile called.
|
||||
// When only rendering layers via the stylesheet, it's possible that we don't
|
||||
// ever visit a tile during rendering.
|
||||
for (const util::ptr<StyleSource> &source : sources) {
|
||||
source->source->finishRender(*this);
|
||||
}
|
||||
|
||||
glFlush();
|
||||
}
|
||||
|
||||
void Painter::renderLayers(util::ptr<StyleLayerGroup> group) {
|
||||
if (!group) {
|
||||
// Make sure that we actually do have a layer group.
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Correctly compute the number of layers recursively beforehand.
|
||||
float strata_thickness = 1.0f / (group->layers.size() + 1);
|
||||
|
||||
// - FIRST PASS ------------------------------------------------------------
|
||||
// Render everything top-to-bottom by using reverse iterators. Render opaque
|
||||
// objects first.
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent++ * 4, ' ') << "OPAQUE {" << std::endl;
|
||||
}
|
||||
int i = 0;
|
||||
for (auto it = group->layers.rbegin(), end = group->layers.rend(); it != end; ++it, ++i) {
|
||||
setOpaque();
|
||||
setStrata(i * strata_thickness);
|
||||
renderLayer(*it);
|
||||
}
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
|
||||
}
|
||||
|
||||
// - SECOND PASS -----------------------------------------------------------
|
||||
// Make a second pass, rendering translucent objects. This time, we render
|
||||
// bottom-to-top.
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent++ * 4, ' ') << "TRANSLUCENT {" << std::endl;
|
||||
}
|
||||
--i;
|
||||
for (auto it = group->layers.begin(), end = group->layers.end(); it != end; ++it, --i) {
|
||||
setTranslucent();
|
||||
setStrata(i * strata_thickness);
|
||||
renderLayer(*it);
|
||||
}
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(--indent * 4, ' ') << "}" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::renderLayer(util::ptr<StyleLayer> layer_desc, const Tile::ID* id, const mat4* matrix) {
|
||||
if (layer_desc->type == StyleLayerType::Background) {
|
||||
// This layer defines a background color/image.
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
|
||||
<< layer_desc->type << ")" << std::endl;
|
||||
}
|
||||
|
||||
renderBackground(layer_desc);
|
||||
} else {
|
||||
// This is a singular layer.
|
||||
if (!layer_desc->bucket) {
|
||||
fprintf(stderr, "[WARNING] layer '%s' is missing bucket\n", layer_desc->id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!layer_desc->bucket->style_source) {
|
||||
fprintf(stderr, "[WARNING] can't find source for layer '%s'\n", layer_desc->id.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
StyleSource const& style_source = *layer_desc->bucket->style_source;
|
||||
|
||||
// Skip this layer if there is no data.
|
||||
if (!style_source.source) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip this layer if it's outside the range of min/maxzoom.
|
||||
// This may occur when there /is/ a bucket created for this layer, but the min/max-zoom
|
||||
// is set to a fractional value, or value that is larger than the source maxzoom.
|
||||
const double zoom = state.getZoom();
|
||||
if (layer_desc->bucket->min_zoom > zoom ||
|
||||
layer_desc->bucket->max_zoom <= zoom) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Abort early if we can already deduce from the bucket type that
|
||||
// we're not going to render anything anyway during this pass.
|
||||
switch (layer_desc->type) {
|
||||
case StyleLayerType::Fill:
|
||||
if (!layer_desc->getProperties<FillProperties>().isVisible()) return;
|
||||
break;
|
||||
case StyleLayerType::Line:
|
||||
if (pass == RenderPass::Opaque) return;
|
||||
if (!layer_desc->getProperties<LineProperties>().isVisible()) return;
|
||||
break;
|
||||
case StyleLayerType::Symbol:
|
||||
if (pass == RenderPass::Opaque) return;
|
||||
if (!layer_desc->getProperties<SymbolProperties>().isVisible()) return;
|
||||
break;
|
||||
case StyleLayerType::Raster:
|
||||
if (pass == RenderPass::Opaque) return;
|
||||
if (!layer_desc->getProperties<RasterProperties>().isVisible()) return;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (debug::renderTree) {
|
||||
std::cout << std::string(indent * 4, ' ') << "- " << layer_desc->id << " ("
|
||||
<< layer_desc->type << ")" << std::endl;
|
||||
}
|
||||
if (!id) {
|
||||
style_source.source->render(*this, layer_desc);
|
||||
} else {
|
||||
style_source.source->render(*this, layer_desc, *id, *matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc, const mat4 &matrix) {
|
||||
assert(tile.data);
|
||||
if (tile.data->hasData(layer_desc) || layer_desc->type == StyleLayerType::Raster) {
|
||||
if (tile.data->hasData(*layer_desc) || layer_desc->type == StyleLayerType::Raster) {
|
||||
gl::group group(util::sprintf<32>("render %d/%d/%d\n", tile.id.z, tile.id.y, tile.id.z));
|
||||
prepareTile(tile);
|
||||
tile.data->render(*this, layer_desc, matrix);
|
||||
@@ -211,15 +365,13 @@ void Painter::renderTileLayer(const Tile& tile, util::ptr<StyleLayer> layer_desc
|
||||
|
||||
void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
|
||||
const BackgroundProperties& properties = layer_desc->getProperties<BackgroundProperties>();
|
||||
const std::shared_ptr<Sprite> sprite = map.getSprite();
|
||||
|
||||
if (properties.image.size() && sprite) {
|
||||
if (properties.image.size()) {
|
||||
if ((properties.opacity >= 1.0f) != (pass == RenderPass::Opaque))
|
||||
return;
|
||||
|
||||
SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
|
||||
SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, *sprite, true);
|
||||
float zoomFraction = map.getState().getZoomFraction();
|
||||
SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image, true);
|
||||
float zoomFraction = state.getZoomFraction();
|
||||
|
||||
useProgram(patternShader->program);
|
||||
patternShader->u_matrix = identityMatrix;
|
||||
@@ -230,8 +382,8 @@ void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
|
||||
|
||||
std::array<float, 2> size = imagePos.size;
|
||||
double lon, lat;
|
||||
map.getLonLat(lon, lat);
|
||||
std::array<float, 2> center = map.getState().locationCoordinate(lon, lat);
|
||||
state.getLonLat(lon, lat);
|
||||
std::array<float, 2> center = state.locationCoordinate(lon, lat);
|
||||
float scale = 1 / std::pow(2, zoomFraction);
|
||||
|
||||
mat3 matrix;
|
||||
@@ -242,10 +394,10 @@ void Painter::renderBackground(util::ptr<StyleLayer> layer_desc) {
|
||||
matrix::translate(matrix, matrix,
|
||||
std::fmod(center[0] * 512, size[0]),
|
||||
std::fmod(center[1] * 512, size[1]));
|
||||
matrix::rotate(matrix, matrix, -map.getState().getAngle());
|
||||
matrix::rotate(matrix, matrix, -state.getAngle());
|
||||
matrix::scale(matrix, matrix,
|
||||
scale * map.getState().getWidth() / 2,
|
||||
-scale * map.getState().getHeight() / 2);
|
||||
scale * state.getWidth() / 2,
|
||||
-scale * state.getHeight() / 2);
|
||||
patternShader->u_patternmatrix = matrix;
|
||||
|
||||
backgroundBuffer.bind();
|
||||
@@ -278,12 +430,12 @@ mat4 Painter::translatedMatrix(const mat4& matrix, const std::array<float, 2> &t
|
||||
return matrix;
|
||||
} else {
|
||||
// TODO: Get rid of the 8 (scaling from 4096 to tile size)
|
||||
const double factor = ((double)(1 << id.z)) / map.getState().getScale() * (4096.0 / util::tileSize);
|
||||
const double factor = ((double)(1 << id.z)) / state.getScale() * (4096.0 / util::tileSize);
|
||||
|
||||
mat4 vtxMatrix;
|
||||
if (anchor == TranslateAnchorType::Viewport) {
|
||||
const double sin_a = std::sin(-map.getState().getAngle());
|
||||
const double cos_a = std::cos(-map.getState().getAngle());
|
||||
const double sin_a = std::sin(-state.getAngle());
|
||||
const double cos_a = std::cos(-state.getAngle());
|
||||
matrix::translate(vtxMatrix, matrix,
|
||||
factor * (translation[0] * cos_a - translation[1] * sin_a),
|
||||
factor * (translation[0] * sin_a + translation[1] * cos_a),
|
||||
|
||||
@@ -25,7 +25,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) {
|
||||
|
||||
// Draw white outline
|
||||
plainShader->u_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
|
||||
lineWidth(4.0f * map.getState().getPixelRatio());
|
||||
lineWidth(4.0f * state.getPixelRatio());
|
||||
bucket.drawLines(*plainShader);
|
||||
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
@@ -36,7 +36,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) {
|
||||
|
||||
// Draw black text.
|
||||
plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }};
|
||||
lineWidth(2.0f * map.getState().getPixelRatio());
|
||||
lineWidth(2.0f * state.getPixelRatio());
|
||||
bucket.drawLines(*plainShader);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@@ -56,7 +56,7 @@ void Painter::renderDebugFrame(const mat4 &matrix) {
|
||||
// draw tile outline
|
||||
tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET(0));
|
||||
plainShader->u_color = {{ 1.0f, 0.0f, 0.0f, 1.0f }};
|
||||
lineWidth(4.0f * map.getState().getPixelRatio());
|
||||
lineWidth(4.0f * state.getPixelRatio());
|
||||
glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)tileBorderBuffer.index());
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@@ -87,14 +87,14 @@ void Painter::renderDebugText(const std::vector<std::string> &strings) {
|
||||
VertexArrayObject debugFontArray;
|
||||
debugFontArray.bind(*plainShader, debugFontBuffer, BUFFER_OFFSET(0));
|
||||
plainShader->u_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
|
||||
lineWidth(4.0f * map.getState().getPixelRatio());
|
||||
lineWidth(4.0f * state.getPixelRatio());
|
||||
glDrawArrays(GL_LINES, 0, (GLsizei)debugFontBuffer.index());
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
glPointSize(2);
|
||||
glDrawArrays(GL_POINTS, 0, (GLsizei)debugFontBuffer.index());
|
||||
#endif
|
||||
plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }};
|
||||
lineWidth(2.0f * map.getState().getPixelRatio());
|
||||
lineWidth(2.0f * state.getPixelRatio());
|
||||
glDrawArrays(GL_LINES, 0, (GLsizei)debugFontBuffer.index());
|
||||
}
|
||||
|
||||
|
||||
@@ -49,8 +49,8 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
|
||||
// Draw the entire line
|
||||
outlineShader->u_world = {{
|
||||
static_cast<float>(map.getState().getFramebufferWidth()),
|
||||
static_cast<float>(map.getState().getFramebufferHeight())
|
||||
static_cast<float>(state.getFramebufferWidth()),
|
||||
static_cast<float>(state.getFramebufferHeight())
|
||||
}};
|
||||
depthRange(strata, 1.0f);
|
||||
bucket.drawVertices(*outlineShader);
|
||||
@@ -58,12 +58,10 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
|
||||
if (pattern) {
|
||||
// Image fill.
|
||||
Sprite &sprite = *map.getSprite();
|
||||
if (pass == RenderPass::Translucent && sprite) {
|
||||
SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
|
||||
const SpriteAtlasPosition pos = spriteAtlas.getPosition(properties.image, sprite, true);
|
||||
const float mix = std::fmod(float(map.getState().getZoom()), 1.0f);
|
||||
const float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
|
||||
if (pass == RenderPass::Translucent) {
|
||||
const SpriteAtlasPosition pos = spriteAtlas.getPosition(properties.image, true);
|
||||
const float mix = std::fmod(float(state.getZoom()), 1.0f);
|
||||
const float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
|
||||
|
||||
mat3 patternMatrix;
|
||||
matrix::identity(patternMatrix);
|
||||
@@ -114,8 +112,8 @@ void Painter::renderFill(FillBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
|
||||
// Draw the entire line
|
||||
outlineShader->u_world = {{
|
||||
static_cast<float>(map.getState().getFramebufferWidth()),
|
||||
static_cast<float>(map.getState().getFramebufferHeight())
|
||||
static_cast<float>(state.getFramebufferWidth()),
|
||||
static_cast<float>(state.getFramebufferHeight())
|
||||
}};
|
||||
|
||||
depthRange(strata + strata_epsilon, 1.0f);
|
||||
|
||||
@@ -15,7 +15,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
|
||||
const LineProperties &properties = layer_desc->getProperties<LineProperties>();
|
||||
|
||||
float antialiasing = 1 / map.getState().getPixelRatio();
|
||||
float antialiasing = 1 / state.getPixelRatio();
|
||||
float width = properties.width;
|
||||
float offset = properties.offset / 2;
|
||||
float blur = properties.blur + antialiasing;
|
||||
@@ -34,7 +34,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
float dash_length = properties.dash_array[0];
|
||||
float dash_gap = properties.dash_array[1];
|
||||
|
||||
float ratio = map.getState().getPixelRatio();
|
||||
float ratio = state.getPixelRatio();
|
||||
mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor);
|
||||
|
||||
depthRange(strata, 1.0f);
|
||||
@@ -45,15 +45,15 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
linejoinShader->u_matrix = vtxMatrix;
|
||||
linejoinShader->u_color = color;
|
||||
linejoinShader->u_world = {{
|
||||
map.getState().getFramebufferWidth() * 0.5f,
|
||||
map.getState().getFramebufferHeight() * 0.5f
|
||||
state.getFramebufferWidth() * 0.5f,
|
||||
state.getFramebufferHeight() * 0.5f
|
||||
}};
|
||||
linejoinShader->u_linewidth = {{
|
||||
((outset - 0.25f) * map.getState().getPixelRatio()),
|
||||
((inset - 0.25f) * map.getState().getPixelRatio())
|
||||
((outset - 0.25f) * state.getPixelRatio()),
|
||||
((inset - 0.25f) * state.getPixelRatio())
|
||||
}};
|
||||
|
||||
float pointSize = std::ceil(map.getState().getPixelRatio() * outset * 2.0);
|
||||
float pointSize = std::ceil(state.getPixelRatio() * outset * 2.0);
|
||||
#if defined(GL_ES_VERSION_2_0)
|
||||
linejoinShader->u_size = pointSize;
|
||||
#else
|
||||
@@ -62,12 +62,11 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
bucket.drawPoints(*linejoinShader);
|
||||
}
|
||||
|
||||
const util::ptr<Sprite> &sprite = map.getSprite();
|
||||
if (properties.image.size() && sprite) {
|
||||
SpriteAtlasPosition imagePos = map.getSpriteAtlas()->getPosition(properties.image, *sprite);
|
||||
if (properties.image.size()) {
|
||||
SpriteAtlasPosition imagePos = spriteAtlas.getPosition(properties.image);
|
||||
|
||||
float factor = 8.0 / std::pow(2, map.getState().getIntegerZoom() - id.z);
|
||||
float fade = std::fmod(map.getState().getZoom(), 1.0);
|
||||
float factor = 8.0 / std::pow(2, state.getIntegerZoom() - id.z);
|
||||
float fade = std::fmod(state.getZoom(), 1.0);
|
||||
|
||||
useProgram(linepatternShader->program);
|
||||
|
||||
@@ -82,7 +81,7 @@ void Painter::renderLine(LineBucket& bucket, util::ptr<StyleLayer> layer_desc, c
|
||||
linepatternShader->u_pattern_br = imagePos.br;
|
||||
linepatternShader->u_fade = fade;
|
||||
|
||||
map.getSpriteAtlas()->bind(true);
|
||||
spriteAtlas.bind(true);
|
||||
glDepthRange(strata + strata_epsilon, 1.0f); // may or may not matter
|
||||
|
||||
bucket.drawLinePatterns(*linepatternShader);
|
||||
|
||||
@@ -31,14 +31,11 @@ void Painter::renderRaster(RasterBucket& bucket, util::ptr<StyleLayer> layer_des
|
||||
return vtxMatrix;
|
||||
}();
|
||||
|
||||
// call updateTiles to get parsed data for sublayers
|
||||
map.updateTiles();
|
||||
|
||||
for (const util::ptr<StyleLayer> &layer : layer_desc->layers->layers) {
|
||||
setOpaque();
|
||||
map.renderLayer(layer, RenderPass::Opaque, &id, &preMatrix);
|
||||
renderLayer(layer, &id, &preMatrix);
|
||||
setTranslucent();
|
||||
map.renderLayer(layer, RenderPass::Translucent, &id, &preMatrix);
|
||||
renderLayer(layer, &id, &preMatrix);
|
||||
}
|
||||
|
||||
if (bucket.properties.blur > 0) {
|
||||
|
||||
@@ -25,10 +25,8 @@ void Painter::renderSDF(SymbolBucket &bucket,
|
||||
mat4 exMatrix;
|
||||
matrix::copy(exMatrix, projMatrix);
|
||||
|
||||
const float angleOffset =
|
||||
bucketProperties.rotation_alignment == RotationAlignmentType::Map
|
||||
? map.getState().getAngle()
|
||||
: 0;
|
||||
bool aligned_with_map = (bucketProperties.rotation_alignment == RotationAlignmentType::Map);
|
||||
const float angleOffset = aligned_with_map ? state.getAngle() : 0;
|
||||
|
||||
if (angleOffset) {
|
||||
matrix::rotate_z(exMatrix, exMatrix, angleOffset);
|
||||
@@ -45,24 +43,24 @@ void Painter::renderSDF(SymbolBucket &bucket,
|
||||
sdfShader.u_texsize = texsize;
|
||||
|
||||
// Convert the -pi..pi to an int8 range.
|
||||
float angle = std::round(map.getState().getAngle() / M_PI * 128);
|
||||
float angle = std::round(state.getAngle() / M_PI * 128);
|
||||
|
||||
// adjust min/max zooms for variable font sies
|
||||
float zoomAdjust = std::log(fontSize / bucketProperties.max_size) / std::log(2);
|
||||
|
||||
sdfShader.u_flip = (aligned_with_map && bucketProperties.keep_upright) ? 1 : 0;
|
||||
sdfShader.u_angle = (int32_t)(angle + 256) % 256;
|
||||
sdfShader.u_flip = (bucket.properties.placement == PlacementType::Line ? 1 : 0);
|
||||
sdfShader.u_zoom = (map.getState().getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
|
||||
sdfShader.u_zoom = (state.getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
|
||||
|
||||
FadeProperties f = frameHistory.getFadeProperties(300_milliseconds);
|
||||
sdfShader.u_fadedist = f.fadedist * 10;
|
||||
sdfShader.u_minfadezoom = std::floor(f.minfadezoom * 10);
|
||||
sdfShader.u_maxfadezoom = std::floor(f.maxfadezoom * 10);
|
||||
sdfShader.u_fadezoom = (map.getState().getNormalizedZoom() + f.bump) * 10;
|
||||
sdfShader.u_fadezoom = (state.getNormalizedZoom() + f.bump) * 10;
|
||||
|
||||
// The default gamma value has to be adjust for the current pixelratio so that we're not
|
||||
// drawing blurry font on retina screens.
|
||||
const float gamma = 0.105 * sdfFontSize / fontSize / map.getState().getPixelRatio();
|
||||
const float gamma = 0.105 * sdfFontSize / fontSize / state.getPixelRatio();
|
||||
|
||||
const float sdfPx = 8.0f;
|
||||
const float blurOffset = 1.19f;
|
||||
@@ -122,35 +120,19 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
if (bucket.hasTextData()) {
|
||||
GlyphAtlas &glyphAtlas = *map.getGlyphAtlas();
|
||||
glyphAtlas.bind();
|
||||
|
||||
renderSDF(bucket,
|
||||
id,
|
||||
matrix,
|
||||
bucket.properties.text,
|
||||
properties.text,
|
||||
24.0f,
|
||||
{{ float(glyphAtlas.width) / 4, float(glyphAtlas.height) / 4 }},
|
||||
*sdfGlyphShader,
|
||||
&SymbolBucket::drawGlyphs);
|
||||
}
|
||||
|
||||
if (bucket.hasIconData()) {
|
||||
bool sdf = bucket.sdfIcons;
|
||||
|
||||
const float angleOffset =
|
||||
bucket.properties.icon.rotation_alignment == RotationAlignmentType::Map
|
||||
? map.getState().getAngle()
|
||||
? state.getAngle()
|
||||
: 0;
|
||||
|
||||
// If layerStyle.size > bucket.info.fontSize then labels may collide
|
||||
const float fontSize = properties.icon.size != 0 ? properties.icon.size : bucket.properties.icon.max_size;
|
||||
const float fontScale = fontSize / 1.0f;
|
||||
|
||||
SpriteAtlas &spriteAtlas = *map.getSpriteAtlas();
|
||||
spriteAtlas.bind(map.getState().isChanging() || bucket.properties.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
|
||||
spriteAtlas.bind(state.isChanging() || bucket.properties.placement == PlacementType::Line || angleOffset != 0 || fontScale != 1 || sdf);
|
||||
|
||||
std::array<float, 2> texsize = {{
|
||||
float(spriteAtlas.getWidth()),
|
||||
@@ -185,19 +167,22 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
|
||||
iconShader->u_texsize = texsize;
|
||||
|
||||
// Convert the -pi..pi to an int8 range.
|
||||
const float angle = std::round(map.getState().getAngle() / M_PI * 128);
|
||||
const float angle = std::round(state.getAngle() / M_PI * 128);
|
||||
|
||||
// adjust min/max zooms for variable font sies
|
||||
float zoomAdjust = std::log(fontSize / bucket.properties.icon.max_size) / std::log(2);
|
||||
|
||||
iconShader->u_angle = (int32_t)(angle + 256) % 256;
|
||||
iconShader->u_flip = bucket.properties.placement == PlacementType::Line ? 1 : 0;
|
||||
iconShader->u_zoom = (map.getState().getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
|
||||
|
||||
bool flip = (bucket.properties.icon.rotation_alignment == RotationAlignmentType::Map)
|
||||
&& bucket.properties.icon.keep_upright;
|
||||
iconShader->u_flip = flip ? 1 : 0;
|
||||
iconShader->u_zoom = (state.getNormalizedZoom() - zoomAdjust) * 10; // current zoom level
|
||||
|
||||
iconShader->u_fadedist = 0 * 10;
|
||||
iconShader->u_minfadezoom = map.getState().getNormalizedZoom() * 10;
|
||||
iconShader->u_maxfadezoom = map.getState().getNormalizedZoom() * 10;
|
||||
iconShader->u_fadezoom = map.getState().getNormalizedZoom() * 10;
|
||||
iconShader->u_minfadezoom = state.getNormalizedZoom() * 10;
|
||||
iconShader->u_maxfadezoom = state.getNormalizedZoom() * 10;
|
||||
iconShader->u_fadezoom = state.getNormalizedZoom() * 10;
|
||||
iconShader->u_opacity = properties.icon.opacity;
|
||||
|
||||
depthRange(strata, 1.0f);
|
||||
@@ -205,5 +190,19 @@ void Painter::renderSymbol(SymbolBucket &bucket, util::ptr<StyleLayer> layer_des
|
||||
}
|
||||
}
|
||||
|
||||
if (bucket.hasTextData()) {
|
||||
glyphAtlas.bind();
|
||||
|
||||
renderSDF(bucket,
|
||||
id,
|
||||
matrix,
|
||||
bucket.properties.text,
|
||||
properties.text,
|
||||
24.0f,
|
||||
{{ float(glyphAtlas.width) / 4, float(glyphAtlas.height) / 4 }},
|
||||
*sdfGlyphShader,
|
||||
&SymbolBucket::drawGlyphs);
|
||||
}
|
||||
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const VectorTileLayer &
|
||||
|
||||
void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpression &filter,
|
||||
const Tile::ID &id, SpriteAtlas &spriteAtlas, Sprite &sprite,
|
||||
GlyphAtlas &glyphAtlas, GlyphStore &glyphStore) {
|
||||
GlyphAtlas & glyphAtlas, GlyphStore &glyphStore) {
|
||||
|
||||
const std::vector<SymbolFeature> features = processFeatures(layer, filter, glyphStore, sprite);
|
||||
|
||||
@@ -148,7 +148,8 @@ void SymbolBucket::addFeatures(const VectorTileLayer &layer, const FilterExpress
|
||||
|
||||
// if feature has icon, get sprite atlas position
|
||||
if (feature.sprite.length()) {
|
||||
image = spriteAtlas.waitForImage(feature.sprite, sprite);
|
||||
sprite.waitUntilLoaded();
|
||||
image = spriteAtlas.getImage(feature.sprite);
|
||||
|
||||
if (sprite.getSpritePosition(feature.sprite).sdf) {
|
||||
sdfIcons = true;
|
||||
|
||||
17
utils/mbgl-config/build.sh
Executable file
17
utils/mbgl-config/build.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
PREFIX=$1
|
||||
PLATFORM=$2
|
||||
|
||||
VARIABLES="#!/bin/bash
|
||||
|
||||
## variables
|
||||
|
||||
CONFIG_MBGL_PREFIX=$PREFIX
|
||||
CONFIG_MBGL_PLATFORM=$PLATFORM
|
||||
"
|
||||
|
||||
echo "$VARIABLES" | cat - utils/mbgl-config/mbgl-config.template.sh \
|
||||
> $PREFIX/bin/mbgl-config
|
||||
|
||||
chmod 755 $PREFIX/bin/mbgl-config
|
||||
61
utils/mbgl-config/mbgl-config.template.sh
Normal file
61
utils/mbgl-config/mbgl-config.template.sh
Normal file
@@ -0,0 +1,61 @@
|
||||
## program below
|
||||
|
||||
usage()
|
||||
{
|
||||
cat <<EOF
|
||||
Usage:
|
||||
mbgl-config [OPTION...]
|
||||
|
||||
Help Options:
|
||||
-h, --help Show help options
|
||||
|
||||
Application Options:
|
||||
--prefix output prefix where mbgl is installed
|
||||
--libs output -L flags
|
||||
--includedir output include directory path
|
||||
EOF
|
||||
|
||||
exit $1
|
||||
}
|
||||
|
||||
echoerr() { echo "$@" 1>&2; }
|
||||
|
||||
if test $# -eq 0; then
|
||||
usage 1
|
||||
fi
|
||||
|
||||
while test $# -gt 0; do
|
||||
case "$1" in
|
||||
esac
|
||||
|
||||
case "$1" in
|
||||
|
||||
--help)
|
||||
usage 0
|
||||
;;
|
||||
|
||||
-h)
|
||||
usage 0
|
||||
;;
|
||||
|
||||
--prefix)
|
||||
echo ${CONFIG_MBGL_PREFIX}
|
||||
;;
|
||||
|
||||
--libs)
|
||||
echo -L${CONFIG_MBGL_PREFIX}/lib -lmbgl -lmbgl-${CONFIG_MBGL_PLATFORM} -lmbgl-headless
|
||||
;;
|
||||
|
||||
--includedir)
|
||||
echo ${CONFIG_MBGL_PREFIX}/include
|
||||
;;
|
||||
|
||||
*)
|
||||
# push to stderr any invalid options
|
||||
echo "unknown option $1" 1>&2;
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
exit 0
|
||||
Reference in New Issue
Block a user