From 604e558d46e0e49a0e3f232610c608bc8f698e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Sat, 10 May 2014 10:32:30 +0200 Subject: [PATCH 1/8] add missing include header --- include/llmr/style/sprite.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/include/llmr/style/sprite.hpp b/include/llmr/style/sprite.hpp index 40da8c4a8..6dd4828e3 100644 --- a/include/llmr/style/sprite.hpp +++ b/include/llmr/style/sprite.hpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include From d964128cc5ab682055f972e74bd617e163bc7bf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 12 May 2014 10:40:10 +0200 Subject: [PATCH 2/8] make sure node is available --- Makefile | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 1b262cc91..d3b74c86b 100644 --- a/Makefile +++ b/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 @@ -52,17 +54,17 @@ run-linux: linux ##### Xcode projects ########################################################### # build Mac OS X project for Xcode -xproj: config.gypi macosx/llmr-app.gyp +xproj: config.gypi macosx/llmr-app.gyp 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 +iproj: config.gypi ios/llmr-app.gyp 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 +lproj: config.gypi linux/llmr-app.gyp node deps/run_gyp linux/llmr-app.gyp --depth=. --generator-output=./build -f xcode open ./build/linux/llmr-app.xcodeproj From b705382b9fdd6df43eadb116b42a692d86416492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 12 May 2014 04:00:38 -0700 Subject: [PATCH 3/8] add cross compile build script [skip ci] --- setup-libraries-cross.sh | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100755 setup-libraries-cross.sh diff --git a/setup-libraries-cross.sh b/setup-libraries-cross.sh new file mode 100755 index 000000000..656f20242 --- /dev/null +++ b/setup-libraries-cross.sh @@ -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 From 6136ab6d213c0aa5e6afba632fc42b5999e70615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 12 May 2014 17:13:26 +0200 Subject: [PATCH 4/8] draw by layer, not by tile This is needed for correctly compositing raster imagery into the map fixes #122 fixes #157 --- bin/style.js | 13 ++++ include/llmr/map/map.hpp | 2 + include/llmr/map/source.hpp | 3 +- include/llmr/renderer/painter.hpp | 30 +++++++-- src/map/map.cpp | 64 ++++++++++++++++-- src/map/source.cpp | 13 +++- src/map/vector_tile_data.cpp | 2 +- src/renderer/painter.cpp | 106 +++++++++++------------------- 8 files changed, 148 insertions(+), 85 deletions(-) diff --git a/bin/style.js b/bin/style.js index 47cdcc1f9..9bbe86631 100644 --- a/bin/style.js +++ b/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" }; diff --git a/include/llmr/map/map.hpp b/include/llmr/map/map.hpp index a9bdf53e5..e82ef42b5 100644 --- a/include/llmr/map/map.hpp +++ b/include/llmr/map/map.hpp @@ -115,6 +115,8 @@ private: // Unconditionally performs a render with the current map state. void render(); + void renderLayers(const std::vector& layers); + void renderLayer(const LayerDescription& layer_desc); private: // If cleared, the next time the render thread attempts to render the map, it will *actually* diff --git a/include/llmr/map/source.hpp b/include/llmr/map/source.hpp index 4da8e6149..7d47d61b7 100644 --- a/include/llmr/map/source.hpp +++ b/include/llmr/map/source.hpp @@ -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 getIDs() const; void updateClipIDs(const std::map &mapping); diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp index a5455ba62..d236ead44 100644 --- a/include/llmr/renderer/painter.hpp +++ b/include/llmr/renderer/painter.hpp @@ -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 &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& tile, const std::vector& layers); - void renderLayer(const std::shared_ptr& tile_data, const LayerDescription& layer_desc); void translateLayer(std::array 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 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; std::unique_ptr outlineShader; diff --git a/src/map/map.cpp b/src/map/map.cpp index dc707ee8f..0155874ac 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -423,14 +423,16 @@ 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(); + source.finishRender(); } painter.renderMatte(); @@ -442,3 +444,55 @@ void Map::render() { update(); } } + +void Map::renderLayers(const std::vector& 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::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::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) { + 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_it->second; + source->render(layer_desc, bucket_desc); + } + } + } +} diff --git a/src/map/source.cpp b/src/map/source.cpp index 91e9d7cb5..c6f3f63e1 100644 --- a/src/map/source.cpp +++ b/src/map/source.cpp @@ -57,16 +57,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 Source::getIDs() const { std::forward_list ptrs; std::transform(tiles.begin(), tiles.end(), std::front_inserter(ptrs), [](const Tile &tile) { diff --git a/src/map/vector_tile_data.cpp b/src/map/vector_tile_data.cpp index c5d3a23ec..6b06b74b4 100644 --- a/src/map/vector_tile_data.cpp +++ b/src/map/vector_tile_data.cpp @@ -40,4 +40,4 @@ void VectorTileData::render(Painter &painter, const LayerDescription& layer_desc assert(databucket_it->second); databucket_it->second->render(painter, layer_desc.name, id); } -} \ No newline at end of file +} diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 5ab9c91d3..6deb884b4 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -167,11 +167,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,86 +180,59 @@ void Painter::clear() { #endif } -void Painter::render(const Tile& tile) { +void Painter::startOpaquePass() { + gl::start_group("opaque pass"); + pass = Opaque; + glDisable(GL_BLEND); + depthMask(true); +} + +void Painter::startTranslucentPass() { + gl::start_group("translucent pass"); + pass = Translucent; + glEnable(GL_BLEND); + depthMask(false); +} + +void Painter::endPass() { + gl::end_group(); +} + +void Painter::setStrata(float value) { + strata = value; +} + +void Painter::prepareTile(const Tile& tile) { + matrix = tile.matrix; + + GLint id = 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) { 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); + prepareTile(tile); + tile.data->render(*this, layer_desc); } else { fprintf(stderr, "tile not parsed yet\n"); } frameHistory.record(map.getAnimationTime(), map.getState().getNormalizedZoom()); +} +void Painter::renderTileDebug(const Tile& tile) { + assert(tile.data); if (debug) { + prepareTile(tile); renderDebugText(tile.data->debugBucket); renderDebugFrame(); } } -void Painter::renderLayers(const std::shared_ptr& tile_data, const std::vector& layers) { - float strata_thickness = 1.0f / (layers.size() + 1); - - // - FIRST PASS ------------------------------------------------------------ - // Render everything top-to-bottom by using reverse iterators. Render opaque - // objects first. - gl::start_group("opaque pass"); - pass = Opaque; - glDisable(GL_BLEND); - depthMask(true); - - typedef std::vector::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. - gl::start_group("translucent pass"); - pass = Translucent; - glEnable(GL_BLEND); - depthMask(false); - - typedef std::vector::const_iterator iterator; - --i; - for (iterator it = layers.begin(), end = layers.end(); it != end; ++it, --i) { - strata = i * strata_thickness; - renderLayer(tile_data, *it); - } - gl::end_group(); -} - -void Painter::renderLayer(const std::shared_ptr& 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::translateLayer(std::array translation, bool reverse) { if (translation[0] || translation[1]) { if (reverse) { From 6ebb4c21f7e5fce9648d066cd2ac79891d78f139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 12 May 2014 18:25:48 +0200 Subject: [PATCH 5/8] clean up gl::group() structure --- src/map/map.cpp | 4 ++++ src/map/source.cpp | 1 + src/renderer/painter.cpp | 12 ++---------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/map/map.cpp b/src/map/map.cpp index 0155874ac..5476f21d3 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -432,6 +432,8 @@ void Map::render() { // ever visit a tile during rendering. for (auto &pair : sources) { Source &source = *pair.second; + const std::string &name = pair.first; + gl::group group(std::string("debug ") + name); source.finishRender(); } @@ -475,6 +477,8 @@ void Map::renderLayers(const std::vector& layers) { } 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 diff --git a/src/map/source.cpp b/src/map/source.cpp index c6f3f63e1..2f2668e7b 100644 --- a/src/map/source.cpp +++ b/src/map/source.cpp @@ -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); diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 6deb884b4..f7b205a31 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -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(); @@ -205,7 +204,7 @@ void Painter::setStrata(float value) { void Painter::prepareTile(const Tile& tile) { matrix = tile.matrix; - GLint id = tile.clip.mask.to_ulong(); + GLint id = (GLint)tile.clip.mask.to_ulong(); GLuint mask = clipMask[tile.clip.length]; glStencilFunc(GL_EQUAL, id, mask); } @@ -225,6 +224,7 @@ void Painter::renderTileLayer(const Tile& tile, const LayerDescription &layer_de } 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); @@ -257,8 +257,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); @@ -304,7 +302,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) { @@ -441,7 +438,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. @@ -512,8 +508,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; @@ -588,8 +582,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) { From d9d9b281c47f79d85395686bf41eb60cc8dfdcf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 12 May 2014 18:25:58 +0200 Subject: [PATCH 6/8] disable texture deleting for now --- src/util/texturepool.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/util/texturepool.cpp b/src/util/texturepool.cpp index 9feadb3db..579f80472 100644 --- a/src/util/texturepool.cpp +++ b/src/util/texturepool.cpp @@ -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(); } } From 2a3377cc4d6cb910dd2f4e637060d7155cbfbf3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 12 May 2014 18:28:21 +0200 Subject: [PATCH 7/8] fix typo fixes #186 --- setup-libraries.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup-libraries.sh b/setup-libraries.sh index 994ee9ed2..cd5dd4385 100755 --- a/setup-libraries.sh +++ b/setup-libraries.sh @@ -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 From 2b1457998638e97660b5b19ba1e05341523030dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Mon, 12 May 2014 19:08:59 +0200 Subject: [PATCH 8/8] only paint layer if it has data refs #184 --- include/llmr/map/raster_tile_data.hpp | 1 + include/llmr/map/tile_data.hpp | 1 + include/llmr/map/vector_tile_data.hpp | 1 + include/llmr/renderer/bucket.hpp | 1 + include/llmr/renderer/debug_bucket.hpp | 1 + include/llmr/renderer/fill_bucket.hpp | 2 +- include/llmr/renderer/line_bucket.hpp | 2 +- include/llmr/renderer/point_bucket.hpp | 3 +-- include/llmr/renderer/raster_bucket.hpp | 1 + include/llmr/renderer/text_bucket.hpp | 6 ++---- src/map/raster_tile_data.cpp | 4 ++++ src/map/vector_tile_data.cpp | 12 ++++++++++++ src/renderer/debug_bucket.cpp | 4 ++++ src/renderer/fill_bucket.cpp | 4 ++-- src/renderer/line_bucket.cpp | 4 ++-- src/renderer/painter.cpp | 18 +++++++----------- src/renderer/point_bucket.cpp | 2 +- src/renderer/raster_bucket.cpp | 4 ++++ src/renderer/text_bucket.cpp | 4 +++- 19 files changed, 50 insertions(+), 25 deletions(-) diff --git a/include/llmr/map/raster_tile_data.hpp b/include/llmr/map/raster_tile_data.hpp index 33243334b..fd72cca9b 100644 --- a/include/llmr/map/raster_tile_data.hpp +++ b/include/llmr/map/raster_tile_data.hpp @@ -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; diff --git a/include/llmr/map/tile_data.hpp b/include/llmr/map/tile_data.hpp index dde48e9c4..65a2892c7 100644 --- a/include/llmr/map/tile_data.hpp +++ b/include/llmr/map/tile_data.hpp @@ -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: diff --git a/include/llmr/map/vector_tile_data.hpp b/include/llmr/map/vector_tile_data.hpp index 6deae7bd7..b9a428dde 100644 --- a/include/llmr/map/vector_tile_data.hpp +++ b/include/llmr/map/vector_tile_data.hpp @@ -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. diff --git a/include/llmr/renderer/bucket.hpp b/include/llmr/renderer/bucket.hpp index 9326aaed1..283a2c94b 100644 --- a/include/llmr/renderer/bucket.hpp +++ b/include/llmr/renderer/bucket.hpp @@ -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() {} }; diff --git a/include/llmr/renderer/debug_bucket.hpp b/include/llmr/renderer/debug_bucket.hpp index f1a7d151f..0b9df57fa 100644 --- a/include/llmr/renderer/debug_bucket.hpp +++ b/include/llmr/renderer/debug_bucket.hpp @@ -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); diff --git a/include/llmr/renderer/fill_bucket.hpp b/include/llmr/renderer/fill_bucket.hpp index 7d2b81287..2d1f61d6a 100644 --- a/include/llmr/renderer/fill_bucket.hpp +++ b/include/llmr/renderer/fill_bucket.hpp @@ -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); diff --git a/include/llmr/renderer/line_bucket.hpp b/include/llmr/renderer/line_bucket.hpp index eb55bba5a..e28c85b7a 100644 --- a/include/llmr/renderer/line_bucket.hpp +++ b/include/llmr/renderer/line_bucket.hpp @@ -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& line); - bool empty() const; bool hasPoints() const; void drawLines(LineShader& shader); diff --git a/include/llmr/renderer/point_bucket.hpp b/include/llmr/renderer/point_bucket.hpp index 6bbaaac8a..2aacbe865 100644 --- a/include/llmr/renderer/point_bucket.hpp +++ b/include/llmr/renderer/point_bucket.hpp @@ -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); diff --git a/include/llmr/renderer/raster_bucket.hpp b/include/llmr/renderer/raster_bucket.hpp index bac87cc72..17e36de77 100644 --- a/include/llmr/renderer/raster_bucket.hpp +++ b/include/llmr/renderer/raster_bucket.hpp @@ -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); diff --git a/include/llmr/renderer/text_bucket.hpp b/include/llmr/renderer/text_bucket.hpp index babec7ea4..2b73aa74d 100644 --- a/include/llmr/renderer/text_bucket.hpp +++ b/include/llmr/renderer/text_bucket.hpp @@ -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 &shapings); - bool empty() const; - void drawGlyphs(TextShader &shader); public: diff --git a/src/map/raster_tile_data.cpp b/src/map/raster_tile_data.cpp index bf3999637..5c522ef2a 100644 --- a/src/map/raster_tile_data.cpp +++ b/src/map/raster_tile_data.cpp @@ -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(); +} diff --git a/src/map/vector_tile_data.cpp b/src/map/vector_tile_data.cpp index 6b06b74b4..84fc4ffc4 100644 --- a/src/map/vector_tile_data.cpp +++ b/src/map/vector_tile_data.cpp @@ -41,3 +41,15 @@ void VectorTileData::render(Painter &painter, const LayerDescription& layer_desc 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; + } +} diff --git a/src/renderer/debug_bucket.cpp b/src/renderer/debug_bucket.cpp index 2cdec50d3..284d8a371 100644 --- a/src/renderer/debug_bucket.cpp +++ b/src/renderer/debug_bucket.cpp @@ -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())); diff --git a/src/renderer/fill_bucket.cpp b/src/renderer/fill_bucket.cpp index 4e553d23d..e4783c5c3 100644 --- a/src/renderer/fill_bucket.cpp +++ b/src/renderer/fill_bucket.cpp @@ -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) { diff --git a/src/renderer/line_bucket.cpp b/src/renderer/line_bucket.cpp index 01d7c52a2..f968c56cb 100644 --- a/src/renderer/line_bucket.cpp +++ b/src/renderer/line_bucket.cpp @@ -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 { diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index f7b205a31..9f1372674 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -210,17 +210,13 @@ void Painter::prepareTile(const Tile& tile) { } void Painter::renderTileLayer(const Tile& tile, const LayerDescription &layer_desc) { - 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) { + 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); - } else { - fprintf(stderr, "tile not parsed yet\n"); + frameHistory.record(map.getAnimationTime(), map.getState().getNormalizedZoom()); } - - frameHistory.record(map.getAnimationTime(), map.getState().getNormalizedZoom()); } void Painter::renderTileDebug(const Tile& tile) { @@ -272,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); @@ -410,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); @@ -496,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; @@ -571,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); diff --git a/src/renderer/point_bucket.cpp b/src/renderer/point_bucket.cpp index d662595c2..fa8482944 100644 --- a/src/renderer/point_bucket.cpp +++ b/src/renderer/point_bucket.cpp @@ -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; } diff --git a/src/renderer/raster_bucket.cpp b/src/renderer/raster_bucket.cpp index ca173680a..c0260023d 100644 --- a/src/renderer/raster_bucket.cpp +++ b/src/renderer/raster_bucket.cpp @@ -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(); +} diff --git a/src/renderer/text_bucket.cpp b/src/renderer/text_bucket.cpp index 5b75ca99f..939a8363e 100644 --- a/src/renderer/text_bucket.cpp +++ b/src/renderer/text_bucket.cpp @@ -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);