Merge branch 'master' of github.com:mapbox/llmr-native into clear-caches
Conflicts: Makefile
This commit is contained in:
12
Makefile
12
Makefile
@@ -7,10 +7,12 @@ V ?= 1
|
||||
all: llmr
|
||||
|
||||
# Builds the regular library
|
||||
llmr: config.gypi llmr.gyp
|
||||
llmr: config.gypi llmr.gyp node
|
||||
deps/run_gyp llmr.gyp --depth=. -Goutput_dir=.. --generator-output=./build/llmr -f make
|
||||
make -C build/llmr V=$(V) llmr-x86
|
||||
|
||||
node:
|
||||
@if [ ! `which node` ]; then echo 'error: depends on node.js. please make sure node is on your PATH'; exit 1; fi;
|
||||
|
||||
##### Test cases ###############################################################
|
||||
|
||||
@@ -40,7 +42,7 @@ run-headless-test: build/test/Makefile
|
||||
|
||||
|
||||
# Builds the linux app with make. This is also used by Travis CI
|
||||
linux: config.gypi linux/llmr-app.gyp
|
||||
linux: config.gypi linux/llmr-app.gyp node
|
||||
deps/run_gyp linux/llmr-app.gyp --depth=. -Goutput_dir=.. --generator-output=./build/linux -f make
|
||||
make -C build/linux V=$(V) linuxapp
|
||||
|
||||
@@ -55,17 +57,17 @@ clear_xcode_cache:
|
||||
@if [[ -d ~/Library/Developer/Xcode/DerivedData/ ]]; then echo 'clearing files in ~/Library/Developer/Xcode/DerivedData/ older than one day'; find ~/Library/Developer/Xcode/DerivedData/llmr-app-* -mtime +1 | xargs rm -rf; fi
|
||||
|
||||
# build Mac OS X project for Xcode
|
||||
xproj: config.gypi macosx/llmr-app.gyp clear_xcode_cache
|
||||
xproj: config.gypi macosx/llmr-app.gyp clear_xcode_cache node
|
||||
deps/run_gyp macosx/llmr-app.gyp --depth=. --generator-output=./build -f xcode
|
||||
open ./build/macosx/llmr-app.xcodeproj
|
||||
|
||||
# build iOS project for Xcode
|
||||
iproj: config.gypi ios/llmr-app.gyp clear_xcode_cache
|
||||
iproj: config.gypi ios/llmr-app.gyp clear_xcode_cache node
|
||||
deps/run_gyp ios/llmr-app.gyp --depth=. --generator-output=./build -f xcode
|
||||
open ./build/ios/llmr-app.xcodeproj
|
||||
|
||||
# build Linux project for Xcode (Runs on Mac OS X too, but without platform-specific code)
|
||||
lproj: config.gypi linux/llmr-app.gyp clear_xcode_cache
|
||||
lproj: config.gypi linux/llmr-app.gyp clear_xcode_cache node
|
||||
deps/run_gyp linux/llmr-app.gyp --depth=. --generator-output=./build -f xcode
|
||||
open ./build/linux/llmr-app.xcodeproj
|
||||
|
||||
|
||||
13
bin/style.js
13
bin/style.js
@@ -2067,6 +2067,19 @@ module.exports = {
|
||||
"opacity": 0.25
|
||||
},
|
||||
}
|
||||
}, {
|
||||
"name": "satellite",
|
||||
"layers": {
|
||||
"building": {
|
||||
"enabled": false,
|
||||
},
|
||||
"building_wall": {
|
||||
"enabled": false,
|
||||
},
|
||||
"building_shadow": {
|
||||
"enabled": false,
|
||||
},
|
||||
}
|
||||
}],
|
||||
"sprite": "/img/maki-sprite"
|
||||
};
|
||||
|
||||
@@ -115,6 +115,8 @@ private:
|
||||
|
||||
// Unconditionally performs a render with the current map state.
|
||||
void render();
|
||||
void renderLayers(const std::vector<LayerDescription>& layers);
|
||||
void renderLayer(const LayerDescription& layer_desc);
|
||||
|
||||
private:
|
||||
// If cleared, the next time the render thread attempts to render the map, it will *actually*
|
||||
|
||||
@@ -17,6 +17,7 @@ public:
|
||||
|
||||
virtual void parse();
|
||||
virtual void render(Painter &painter, const LayerDescription& layer_desc);
|
||||
virtual bool hasData(const LayerDescription& layer_desc) const;
|
||||
|
||||
protected:
|
||||
RasterBucket bucket;
|
||||
|
||||
@@ -36,7 +36,8 @@ public:
|
||||
|
||||
bool update();
|
||||
size_t prepareRender(const TransformState &transform);
|
||||
void render();
|
||||
void render(const LayerDescription& layer_desc, const BucketDescription &bucket_desc);
|
||||
void finishRender();
|
||||
|
||||
std::forward_list<Tile::ID> getIDs() const;
|
||||
void updateClipIDs(const std::map<Tile::ID, ClipID> &mapping);
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
// Override this in the child class.
|
||||
virtual void parse() = 0;
|
||||
virtual void render(Painter &painter, const LayerDescription& layer_desc) = 0;
|
||||
virtual bool hasData(const LayerDescription& layer_desc) const = 0;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
|
||||
virtual void parse();
|
||||
virtual void render(Painter &painter, const LayerDescription& layer_desc);
|
||||
virtual bool hasData(const LayerDescription& layer_desc) const;
|
||||
|
||||
protected:
|
||||
// Holds the actual geometries in this tile.
|
||||
|
||||
@@ -12,6 +12,7 @@ class Painter;
|
||||
class Bucket : private util::noncopyable {
|
||||
public:
|
||||
virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id) = 0;
|
||||
virtual bool hasData() const = 0;
|
||||
virtual ~Bucket() {}
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ public:
|
||||
DebugBucket(DebugFontBuffer& fontBuffer);
|
||||
|
||||
virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id);
|
||||
virtual bool hasData() const;
|
||||
|
||||
void drawLines(PlainShader& shader);
|
||||
void drawPoints(PlainShader& shader);
|
||||
|
||||
@@ -45,9 +45,9 @@ public:
|
||||
~FillBucket();
|
||||
|
||||
virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id);
|
||||
virtual bool hasData() const;
|
||||
|
||||
void addGeometry(pbf& data);
|
||||
bool empty() const;
|
||||
void tessellate();
|
||||
|
||||
void drawElements(PlainShader& shader);
|
||||
|
||||
@@ -28,11 +28,11 @@ public:
|
||||
const BucketDescription& bucket_desc);
|
||||
|
||||
virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id);
|
||||
virtual bool hasData() const;
|
||||
|
||||
void addGeometry(pbf& data);
|
||||
void addGeometry(const std::vector<Coordinate>& line);
|
||||
|
||||
bool empty() const;
|
||||
bool hasPoints() const;
|
||||
|
||||
void drawLines(LineShader& shader);
|
||||
|
||||
@@ -43,11 +43,23 @@ public:
|
||||
|
||||
void setup();
|
||||
void clear();
|
||||
|
||||
// Updates the default matrices to the current viewport dimensions.
|
||||
void changeMatrix();
|
||||
void render(const Tile& tile);
|
||||
|
||||
// Renders a particular layer from a tile.
|
||||
void renderTileLayer(const Tile& tile, const LayerDescription &layer_desc);
|
||||
|
||||
// Renders debug information for a tile.
|
||||
void renderTileDebug(const Tile& tile);
|
||||
|
||||
// Renders the backdrop of the OpenGL view. This also paints in areas where we don't have any
|
||||
// tiles whatsoever.
|
||||
void renderMatte();
|
||||
|
||||
// Renders the red debug frame around a tile, visualizing its perimeter.
|
||||
void renderDebugFrame();
|
||||
|
||||
void renderDebugText(DebugBucket& bucket);
|
||||
void renderDebugText(const std::vector<std::string> &strings);
|
||||
void renderFill(FillBucket& bucket, const std::string& layer_name, const Tile::ID& id);
|
||||
@@ -61,19 +73,24 @@ public:
|
||||
// Changes whether debug information is drawn onto the map
|
||||
void setDebug(bool enabled);
|
||||
|
||||
// Opaque/Translucent pass setting
|
||||
void startOpaquePass();
|
||||
void startTranslucentPass();
|
||||
void endPass();
|
||||
|
||||
// Configures the painter strata that is used for early z-culling of fragments.
|
||||
void setStrata(float strata);
|
||||
|
||||
void prepareClippingMask();
|
||||
void drawClippingMask(const mat4& matrix, const ClipID& clip);
|
||||
void finishClippingMask();
|
||||
|
||||
void setCurrentSourceName(const std::string &name);
|
||||
|
||||
bool needsAnimation() const;
|
||||
private:
|
||||
void setupShaders();
|
||||
void renderLayers(const std::shared_ptr<TileData>& tile, const std::vector<LayerDescription>& layers);
|
||||
void renderLayer(const std::shared_ptr<TileData>& tile_data, const LayerDescription& layer_desc);
|
||||
void translateLayer(std::array<float, 2> translation, bool reverse = false);
|
||||
|
||||
void prepareTile(const Tile& tile);
|
||||
void useProgram(uint32_t program);
|
||||
void lineWidth(float lineWidth);
|
||||
void depthMask(bool value);
|
||||
@@ -96,9 +113,8 @@ private:
|
||||
bool gl_depthMask = true;
|
||||
std::array<uint16_t, 2> gl_viewport = {{ 0, 0 }};
|
||||
float strata = 0;
|
||||
const float strata_epsilon = 1.0f / (1 << 16);
|
||||
enum { Opaque, Translucent } pass = Opaque;
|
||||
std::string currentSourceName;
|
||||
const float strata_epsilon = 1.0f / (1 << 16);
|
||||
|
||||
std::unique_ptr<PlainShader> plainShader;
|
||||
std::unique_ptr<OutlineShader> outlineShader;
|
||||
|
||||
@@ -28,11 +28,10 @@ public:
|
||||
const BucketDescription& bucket_desc);
|
||||
|
||||
virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id);
|
||||
virtual bool hasData() const;
|
||||
|
||||
void addGeometry(pbf& data);
|
||||
|
||||
bool hasPoints() const;
|
||||
|
||||
void drawPoints(PointShader& shader);
|
||||
void drawPoints(DotShader& shader);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ public:
|
||||
RasterBucket(Texturepool &texturepool);
|
||||
|
||||
virtual void render(Painter& painter, const std::string& layer_name, const Tile::ID& id);
|
||||
virtual bool hasData() const;
|
||||
|
||||
bool setImage(const std::string &data);
|
||||
|
||||
|
||||
@@ -29,8 +29,8 @@ public:
|
||||
TriangleElementsBuffer &triangleElementsBuffer,
|
||||
const BucketDescription &bucket_desc, Placement &placement);
|
||||
|
||||
virtual void render(Painter &painter, const std::string &layer_name,
|
||||
const Tile::ID &id);
|
||||
virtual void render(Painter &painter, const std::string &layer_name, const Tile::ID &id);
|
||||
virtual bool hasData() const;
|
||||
|
||||
void addGlyphs(const PlacedGlyphs &glyphs, float placementZoom,
|
||||
PlacementRange placementRange, float zoom);
|
||||
@@ -39,8 +39,6 @@ public:
|
||||
const IndexedFaces &faces,
|
||||
const std::map<Value, Shaping> &shapings);
|
||||
|
||||
bool empty() const;
|
||||
|
||||
void drawGlyphs(TextShader &shader);
|
||||
|
||||
public:
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <memory>
|
||||
#include <atomic>
|
||||
|
||||
#include <llmr/util/raster.hpp>
|
||||
#include <llmr/util/vec.hpp>
|
||||
|
||||
29
setup-libraries-cross.sh
Executable file
29
setup-libraries-cross.sh
Executable file
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
set -e -u
|
||||
|
||||
|
||||
export CXX11=true
|
||||
|
||||
export SYSROOT=`pwd`/../rootfs
|
||||
export SDK_PATH=`pwd`/../arm-linux-gnueabi-linaro_4.8.3-2014.04
|
||||
export V=1
|
||||
|
||||
cd mapnik-packaging/osx/
|
||||
|
||||
source Linaro-softfp.sh
|
||||
echo $PATH
|
||||
if [ ! -f out/build-cpp11-libstdcpp-gcc-arm-linux-gnueabi/lib/libpng.a ] ; then ./scripts/build_png.sh ; fi
|
||||
# if [ ! -f out/build-cpp11-libstdcpp-gcc-arm-linux-gnueabi/lib/libglfw3.a ] ; then ./scripts/build_glfw.sh ; fi
|
||||
if [ ! -f out/build-cpp11-libstdcpp-gcc-arm-linux-gnueabi/lib/libuv.a ] ; then ./scripts/build_libuv.sh ; fi
|
||||
if [ ! -f out/build-cpp11-libstdcpp-gcc-arm-linux-gnueabi/lib/libssl.a ] ; then ./scripts/build_openssl.sh ; fi
|
||||
# if [ ! -f out/build-cpp11-libstdcpp-gcc-x86_64/lib/libcurl.a ] ; then ./scripts/build_curl.sh ; fi
|
||||
# if [ ! -d out/build-cpp11-libstdcpp-gcc-arm-linux-gnueabi/include/boost ] ; then ./scripts/build_boost.sh `pwd`/../../src/ `pwd`/../../linux/ `pwd`/../../common/ ; fi
|
||||
|
||||
|
||||
|
||||
# cd ../../
|
||||
# ./configure \
|
||||
# --pkg-config-root=`pwd`/mapnik-packaging/osx/out/build-cpp11-libstdcpp-gcc-x86_64/lib/pkgconfig \
|
||||
# --boost=`pwd`/mapnik-packaging/osx/out/build-cpp11-libstdcpp-gcc-x86_64
|
||||
|
||||
# fi
|
||||
@@ -25,7 +25,7 @@ fi
|
||||
|
||||
if [[ $MISSING_DEPS != false ]]; then
|
||||
if [ ${UNAME} = 'Darwin' ]; then
|
||||
echo 'Please run "brew install autoconf automake libtool makedependc cmake" and then re-run ./setup-libraries.sh'
|
||||
echo 'Please run "brew install autoconf automake libtool makedepend cmake" and then re-run ./setup-libraries.sh'
|
||||
elif [ ${UNAME} = 'Linux' ]; then
|
||||
echo 'Please run "sudo apt-get install automake libtool xutils-dev cmake" and then re-run ./setup-libraries.sh'
|
||||
fi
|
||||
|
||||
@@ -423,14 +423,18 @@ void Map::render() {
|
||||
|
||||
painter.finishClippingMask();
|
||||
|
||||
// Render per layer in the stylesheet.
|
||||
renderLayers(style.layers);
|
||||
|
||||
// Then, render each source's tiles. TODO: handle more than one
|
||||
// vector source.
|
||||
|
||||
// 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 (auto &pair : sources) {
|
||||
Source &source = *pair.second;
|
||||
painter.setCurrentSourceName(pair.first);
|
||||
source.render();
|
||||
const std::string &name = pair.first;
|
||||
gl::group group(std::string("debug ") + name);
|
||||
source.finishRender();
|
||||
}
|
||||
|
||||
painter.renderMatte();
|
||||
@@ -442,3 +446,57 @@ void Map::render() {
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void Map::renderLayers(const std::vector<LayerDescription>& layers) {
|
||||
// TODO: Correctly compute the number of layers recursively beforehand.
|
||||
float strata_thickness = 1.0f / (layers.size() + 1);
|
||||
|
||||
// - FIRST PASS ------------------------------------------------------------
|
||||
// Render everything top-to-bottom by using reverse iterators. Render opaque
|
||||
// objects first.
|
||||
painter.startOpaquePass();
|
||||
typedef std::vector<LayerDescription>::const_reverse_iterator riterator;
|
||||
int i = 0;
|
||||
for (riterator it = layers.rbegin(), end = layers.rend(); it != end; ++it, ++i) {
|
||||
painter.setStrata(i * strata_thickness);
|
||||
renderLayer(*it);
|
||||
}
|
||||
painter.endPass();
|
||||
|
||||
// - SECOND PASS -----------------------------------------------------------
|
||||
// Make a second pass, rendering translucent objects. This time, we render
|
||||
// bottom-to-top.
|
||||
painter.startTranslucentPass();
|
||||
typedef std::vector<LayerDescription>::const_iterator iterator;
|
||||
--i;
|
||||
for (iterator it = layers.begin(), end = layers.end(); it != end; ++it, --i) {
|
||||
painter.setStrata(i * strata_thickness);
|
||||
renderLayer(*it);
|
||||
}
|
||||
painter.endPass();
|
||||
}
|
||||
|
||||
void Map::renderLayer(const LayerDescription& layer_desc) {
|
||||
gl::group group(std::string("layer: ") + layer_desc.name);
|
||||
|
||||
if (layer_desc.child_layer.size()) {
|
||||
// This is a layer group.
|
||||
// TODO: create framebuffer
|
||||
renderLayers(layer_desc.child_layer);
|
||||
// TODO: render framebuffer on previous framebuffer
|
||||
} else {
|
||||
// This is a singular layer. Try to find the bucket associated with
|
||||
// this layer and render it.
|
||||
auto bucket_it = style.buckets.find(layer_desc.bucket_name);
|
||||
if (bucket_it != style.buckets.end()) {
|
||||
const BucketDescription &bucket_desc = bucket_it->second;
|
||||
|
||||
// Find the source and render all tiles in it.
|
||||
auto source_it = sources.find(bucket_desc.source_name);
|
||||
if (source_it != sources.end()) {
|
||||
const std::unique_ptr<Source> &source = source_it->second;
|
||||
source->render(layer_desc, bucket_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,3 +28,7 @@ void RasterTileData::parse() {
|
||||
void RasterTileData::render(Painter &painter, const LayerDescription& layer_desc) {
|
||||
bucket.render(painter, layer_desc.name, id);
|
||||
}
|
||||
|
||||
bool RasterTileData::hasData(const LayerDescription& layer_desc) const {
|
||||
return bucket.hasData();
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ size_t Source::prepareRender(const TransformState &transform) {
|
||||
|
||||
size_t masks = 0;
|
||||
for (Tile& tile : tiles) {
|
||||
gl::group group(util::sprintf<32>("mask %d/%d/%d", tile.id.z, tile.id.y, tile.id.z));
|
||||
transform.matrixFor(tile.matrix, tile.id);
|
||||
matrix::multiply(tile.matrix, painter.projMatrix, tile.matrix);
|
||||
painter.drawClippingMask(tile.matrix, tile.clip);
|
||||
@@ -57,16 +58,25 @@ size_t Source::prepareRender(const TransformState &transform) {
|
||||
return masks;
|
||||
}
|
||||
|
||||
void Source::render() {
|
||||
void Source::render(const LayerDescription& layer_desc, const BucketDescription &bucket_desc) {
|
||||
if (!enabled) return;
|
||||
|
||||
for (const Tile& tile : tiles) {
|
||||
if (tile.data && tile.data->state == TileData::State::parsed) {
|
||||
painter.render(tile);
|
||||
painter.renderTileLayer(tile, layer_desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Source::finishRender() {
|
||||
if (!enabled) return;
|
||||
|
||||
for (const Tile& tile : tiles) {
|
||||
painter.renderTileDebug(tile);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::forward_list<Tile::ID> Source::getIDs() const {
|
||||
std::forward_list<Tile::ID> ptrs;
|
||||
std::transform(tiles.begin(), tiles.end(), std::front_inserter(ptrs), [](const Tile &tile) {
|
||||
|
||||
@@ -40,4 +40,16 @@ void VectorTileData::render(Painter &painter, const LayerDescription& layer_desc
|
||||
assert(databucket_it->second);
|
||||
databucket_it->second->render(painter, layer_desc.name, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VectorTileData::hasData(const LayerDescription& layer_desc) const {
|
||||
if (state != State::parsed) return false;
|
||||
|
||||
auto databucket_it = buckets.find(layer_desc.bucket_name);
|
||||
if (databucket_it != buckets.end()) {
|
||||
assert(databucket_it->second);
|
||||
return databucket_it->second->hasData();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@ void DebugBucket::render(Painter& painter, const std::string& /*layer_name*/, co
|
||||
painter.renderDebugText(*this);
|
||||
}
|
||||
|
||||
bool DebugBucket::hasData() const {
|
||||
return fontBuffer.index() > 0;
|
||||
}
|
||||
|
||||
void DebugBucket::drawLines(PlainShader& shader) {
|
||||
array.bind(shader, fontBuffer, BUFFER_OFFSET(0));
|
||||
glDrawArrays(GL_LINES, 0, (GLsizei)(fontBuffer.index()));
|
||||
|
||||
@@ -206,8 +206,8 @@ void FillBucket::render(Painter& painter, const std::string& layer_name, const T
|
||||
painter.renderFill(*this, layer_name, id);
|
||||
}
|
||||
|
||||
bool FillBucket::empty() const {
|
||||
return triangleGroups.empty() && lineGroups.empty();
|
||||
bool FillBucket::hasData() const {
|
||||
return !triangleGroups.empty() || !lineGroups.empty();
|
||||
}
|
||||
|
||||
void FillBucket::drawElements(PlainShader& shader) {
|
||||
|
||||
@@ -348,8 +348,8 @@ void LineBucket::render(Painter& painter, const std::string& layer_name, const T
|
||||
painter.renderLine(*this, layer_name, id);
|
||||
}
|
||||
|
||||
bool LineBucket::empty() const {
|
||||
return triangleGroups.empty();
|
||||
bool LineBucket::hasData() const {
|
||||
return !triangleGroups.empty() || !pointGroups.empty();
|
||||
}
|
||||
|
||||
bool LineBucket::hasPoints() const {
|
||||
|
||||
@@ -141,7 +141,6 @@ void Painter::prepareClippingMask() {
|
||||
}
|
||||
|
||||
void Painter::drawClippingMask(const mat4& matrix, const ClipID &clip) {
|
||||
gl::group group("mask");
|
||||
plainShader->setMatrix(matrix);
|
||||
|
||||
GLint id = clip.mask.to_ulong();
|
||||
@@ -167,11 +166,6 @@ void Painter::finishClippingMask() {
|
||||
gl::end_group();
|
||||
}
|
||||
|
||||
void Painter::setCurrentSourceName(const std::string &name) {
|
||||
currentSourceName = name;
|
||||
}
|
||||
|
||||
|
||||
void Painter::clear() {
|
||||
gl::group group("clear");
|
||||
glStencilMask(0xFF);
|
||||
@@ -185,83 +179,53 @@ void Painter::clear() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void Painter::render(const Tile& tile) {
|
||||
gl::group group(util::sprintf<32>("render %d/%d/%d", tile.id.z, tile.id.y, tile.id.z));
|
||||
|
||||
assert(tile.data);
|
||||
if (tile.data->state == TileData::State::parsed) {
|
||||
matrix = tile.matrix;
|
||||
GLint id = tile.clip.mask.to_ulong();
|
||||
GLuint mask = clipMask[tile.clip.length];
|
||||
|
||||
glStencilFunc(GL_EQUAL, id, mask);
|
||||
|
||||
renderLayers(tile.data, map.getStyle().layers);
|
||||
} else {
|
||||
fprintf(stderr, "tile not parsed yet\n");
|
||||
}
|
||||
|
||||
frameHistory.record(map.getAnimationTime(), map.getState().getNormalizedZoom());
|
||||
|
||||
if (debug) {
|
||||
renderDebugText(tile.data->debugBucket);
|
||||
renderDebugFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::renderLayers(const std::shared_ptr<TileData>& tile_data, const std::vector<LayerDescription>& layers) {
|
||||
float strata_thickness = 1.0f / (layers.size() + 1);
|
||||
|
||||
// - FIRST PASS ------------------------------------------------------------
|
||||
// Render everything top-to-bottom by using reverse iterators. Render opaque
|
||||
// objects first.
|
||||
void Painter::startOpaquePass() {
|
||||
gl::start_group("opaque pass");
|
||||
pass = Opaque;
|
||||
glDisable(GL_BLEND);
|
||||
depthMask(true);
|
||||
}
|
||||
|
||||
typedef std::vector<LayerDescription>::const_reverse_iterator riterator;
|
||||
int i = 0;
|
||||
for (riterator it = layers.rbegin(), end = layers.rend(); it != end; ++it, ++i) {
|
||||
strata = i * strata_thickness;
|
||||
renderLayer(tile_data, *it);
|
||||
}
|
||||
gl::end_group();
|
||||
|
||||
// - SECOND PASS -----------------------------------------------------------
|
||||
// Make a second pass, rendering translucent objects. This time, we render
|
||||
// bottom-to-top.
|
||||
void Painter::startTranslucentPass() {
|
||||
gl::start_group("translucent pass");
|
||||
pass = Translucent;
|
||||
glEnable(GL_BLEND);
|
||||
depthMask(false);
|
||||
}
|
||||
|
||||
typedef std::vector<LayerDescription>::const_iterator iterator;
|
||||
--i;
|
||||
for (iterator it = layers.begin(), end = layers.end(); it != end; ++it, --i) {
|
||||
strata = i * strata_thickness;
|
||||
renderLayer(tile_data, *it);
|
||||
}
|
||||
void Painter::endPass() {
|
||||
gl::end_group();
|
||||
}
|
||||
|
||||
void Painter::renderLayer(const std::shared_ptr<TileData>& tile_data, const LayerDescription& layer_desc) {
|
||||
if (layer_desc.child_layer.size()) {
|
||||
// This is a layer group.
|
||||
// TODO: create framebuffer
|
||||
renderLayers(tile_data, layer_desc.child_layer);
|
||||
// TODO: render framebuffer on previous framebuffer
|
||||
} else {
|
||||
// This is a singular layer. Try to find the bucket associated with
|
||||
// this layer and render it.
|
||||
auto bucket_it = map.getStyle().buckets.find(layer_desc.bucket_name);
|
||||
if (bucket_it != map.getStyle().buckets.end()) {
|
||||
const BucketDescription &bucket = bucket_it->second;
|
||||
// Only try to render the bucket if it draws data from the current source.
|
||||
if (bucket.source_name == currentSourceName) {
|
||||
tile_data->render(*this, layer_desc);
|
||||
}
|
||||
}
|
||||
void Painter::setStrata(float value) {
|
||||
strata = value;
|
||||
}
|
||||
|
||||
void Painter::prepareTile(const Tile& tile) {
|
||||
matrix = tile.matrix;
|
||||
|
||||
GLint id = (GLint)tile.clip.mask.to_ulong();
|
||||
GLuint mask = clipMask[tile.clip.length];
|
||||
glStencilFunc(GL_EQUAL, id, mask);
|
||||
}
|
||||
|
||||
void Painter::renderTileLayer(const Tile& tile, const LayerDescription &layer_desc) {
|
||||
assert(tile.data);
|
||||
if (tile.data->hasData(layer_desc)) {
|
||||
gl::group group(util::sprintf<32>("render %d/%d/%d", tile.id.z, tile.id.y, tile.id.z));
|
||||
prepareTile(tile);
|
||||
tile.data->render(*this, layer_desc);
|
||||
frameHistory.record(map.getAnimationTime(), map.getState().getNormalizedZoom());
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::renderTileDebug(const Tile& tile) {
|
||||
gl::group group(util::sprintf<32>("debug %d/%d/%d", tile.id.z, tile.id.y, tile.id.z));
|
||||
assert(tile.data);
|
||||
if (debug) {
|
||||
prepareTile(tile);
|
||||
renderDebugText(tile.data->debugBucket);
|
||||
renderDebugFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,8 +253,6 @@ void Painter::renderRaster(RasterBucket& bucket, const std::string& layer_name,
|
||||
const RasterProperties& properties = raster_properties_it->second;
|
||||
if (!properties.enabled) return;
|
||||
|
||||
gl::group group(layer_name + " (raster)");
|
||||
|
||||
depthMask(false);
|
||||
|
||||
useProgram(rasterShader->program);
|
||||
@@ -306,7 +268,7 @@ void Painter::renderRaster(RasterBucket& bucket, const std::string& layer_name,
|
||||
|
||||
void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, const Tile::ID& id) {
|
||||
// Abort early.
|
||||
if (bucket.empty()) return;
|
||||
if (!bucket.hasData()) return;
|
||||
|
||||
auto fill_properties = map.getStyle().computed.fills;
|
||||
auto fill_properties_it = fill_properties.find(layer_name);
|
||||
@@ -336,7 +298,6 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
|
||||
|
||||
translateLayer(properties.translate);
|
||||
|
||||
gl::group group(layer_name + " (fill)");
|
||||
// Because we're drawing top-to-bottom, and we update the stencil mask
|
||||
// below, we have to draw the outline first (!)
|
||||
if (outline && pass == Translucent) {
|
||||
@@ -445,7 +406,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
|
||||
void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, const Tile::ID& /*id*/) {
|
||||
// Abort early.
|
||||
if (pass == Opaque) return;
|
||||
if (bucket.empty()) return;
|
||||
if (!bucket.hasData()) return;
|
||||
|
||||
auto line_properties = map.getStyle().computed.lines;
|
||||
auto line_properties_it = line_properties.find(layer_name);
|
||||
@@ -473,7 +434,6 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
|
||||
|
||||
translateLayer(properties.translate);
|
||||
|
||||
gl::group group(layer_name + " (line)");
|
||||
glDepthRange(strata, 1.0f);
|
||||
|
||||
// We're only drawing end caps + round line joins if the line is > 2px. Otherwise, they aren't visible anyway.
|
||||
@@ -532,7 +492,7 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
|
||||
|
||||
void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, const Tile::ID& /*id&*/) {
|
||||
// Abort early.
|
||||
if (!bucket.hasPoints()) return;
|
||||
if (!bucket.hasData()) return;
|
||||
if (pass == Opaque) return;
|
||||
|
||||
auto point_properties = map.getStyle().computed.points;
|
||||
@@ -544,8 +504,6 @@ void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, co
|
||||
|
||||
translateLayer(properties.translate);
|
||||
|
||||
gl::group group(layer_name + " (point)");
|
||||
|
||||
Color color = properties.color;
|
||||
color[0] *= properties.opacity;
|
||||
color[1] *= properties.opacity;
|
||||
@@ -609,7 +567,7 @@ void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, co
|
||||
void Painter::renderText(TextBucket& bucket, const std::string& layer_name, const Tile::ID& /*id*/) {
|
||||
// Abort early.
|
||||
if (pass == Opaque) return;
|
||||
if (bucket.empty()) return;
|
||||
if (!bucket.hasData()) return;
|
||||
|
||||
auto text_properties = map.getStyle().computed.texts;
|
||||
auto text_properties_it = text_properties.find(layer_name);
|
||||
@@ -620,8 +578,6 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
|
||||
|
||||
translateLayer(properties.translate);
|
||||
|
||||
gl::group group(layer_name + " (text)");
|
||||
|
||||
mat4 exMatrix;
|
||||
matrix::copy(exMatrix, projMatrix);
|
||||
if (bucket.geom_desc.path == TextPathType::Curve) {
|
||||
|
||||
@@ -41,7 +41,7 @@ void PointBucket::render(Painter& painter, const std::string& layer_name, const
|
||||
painter.renderPoint(*this, layer_name, id);
|
||||
}
|
||||
|
||||
bool PointBucket::hasPoints() const {
|
||||
bool PointBucket::hasData() const {
|
||||
return vertex_end > 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,3 +21,7 @@ void RasterBucket::drawRaster(RasterShader& shader, VertexBuffer &vertices, Vert
|
||||
array.bind(shader, vertices, BUFFER_OFFSET(0));
|
||||
glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertices.index());
|
||||
}
|
||||
|
||||
bool RasterBucket::hasData() const {
|
||||
return raster.isLoaded();
|
||||
}
|
||||
|
||||
@@ -146,7 +146,9 @@ void TextBucket::render(Painter &painter, const std::string &layer_name,
|
||||
painter.renderText(*this, layer_name, id);
|
||||
}
|
||||
|
||||
bool TextBucket::empty() const { return triangleGroups.empty(); }
|
||||
bool TextBucket::hasData() const {
|
||||
return !triangleGroups.empty();
|
||||
}
|
||||
|
||||
void TextBucket::drawGlyphs(TextShader &shader) {
|
||||
char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer.itemSize);
|
||||
|
||||
@@ -36,7 +36,8 @@ void Texturepool::removeTextureID(GLuint texture_id) {
|
||||
}
|
||||
|
||||
if (needs_clear) {
|
||||
clearTextureIDs();
|
||||
// TODO: We need to find a better way to deal with texture pool cleanup
|
||||
// clearTextureIDs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user