diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-01-14 16:29:20 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-01-14 16:29:20 +0100 |
commit | 60a8fdca5727bc57bd6526e5447e2cc41db1ada8 (patch) | |
tree | b73da9de7e55b1f5257822885c68a14ff9fee9bc | |
parent | 654972bb3feb1f451a820afbc7c46e7e502ce687 (diff) | |
download | qtlocation-mapboxgl-60a8fdca5727bc57bd6526e5447e2cc41db1ada8.tar.gz |
fix runtime errors
-rw-r--r-- | include/llmr/geometry/linevertexbuffer.hpp | 1 | ||||
-rw-r--r-- | include/llmr/map/map.hpp | 6 | ||||
-rw-r--r-- | include/llmr/map/tile.hpp | 11 | ||||
-rw-r--r-- | include/llmr/platform/platform.hpp | 4 | ||||
-rw-r--r-- | include/llmr/renderer/painter.hpp | 4 | ||||
-rw-r--r-- | include/llmr/util/vec2.hpp | 18 | ||||
-rw-r--r-- | macosx/main.mm | 35 | ||||
-rw-r--r-- | src/geometry/linevertexbuffer.cpp | 8 | ||||
-rw-r--r-- | src/map/map.cpp | 34 | ||||
-rw-r--r-- | src/map/pbf.hpp | 57 | ||||
-rw-r--r-- | src/map/tile.cpp | 80 | ||||
-rw-r--r-- | src/map/transform.cpp | 2 | ||||
-rw-r--r-- | src/renderer/painter.cpp | 4 |
13 files changed, 170 insertions, 94 deletions
diff --git a/include/llmr/geometry/linevertexbuffer.hpp b/include/llmr/geometry/linevertexbuffer.hpp index 4d23de9154..0583297f7b 100644 --- a/include/llmr/geometry/linevertexbuffer.hpp +++ b/include/llmr/geometry/linevertexbuffer.hpp @@ -8,6 +8,7 @@ namespace llmr { class linevertexbuffer { public: linevertexbuffer(); + ~linevertexbuffer(); void addDegenerate(); void addCoordinate(int16_t x, int16_t y); diff --git a/include/llmr/map/map.hpp b/include/llmr/map/map.hpp index 745ccce89d..71387c0934 100644 --- a/include/llmr/map/map.hpp +++ b/include/llmr/map/map.hpp @@ -22,8 +22,8 @@ public: void moveBy(double dx, double dy); void scaleBy(double ds, double cx, double cy); void rotateBy(double cx, double cy, double sx, double sy, double ex, double ey); - void tileLoaded(tile *tile); - void tileFailed(tile *tile); + void tileLoaded(std::shared_ptr<tile> tile); + void tileFailed(std::shared_ptr<tile> tile); private: void updateTiles(); @@ -35,7 +35,7 @@ private: // int32_t min_zoom; // int32_t max_zoom; - std::vector<tile *> tiles; + std::vector<std::shared_ptr<tile>> tiles; }; } diff --git a/include/llmr/map/tile.hpp b/include/llmr/map/tile.hpp index 95d0593f72..063e6a90bd 100644 --- a/include/llmr/map/tile.hpp +++ b/include/llmr/map/tile.hpp @@ -5,13 +5,18 @@ #include <stdint.h> #include <vector> +#include <mutex> #include <llmr/util/vec2.hpp> namespace llmr { class tile { public: + typedef std::shared_ptr<tile> ptr; + +public: tile(int32_t z, int32_t x, int32_t y); + ~tile(); void setData(uint8_t *data, uint32_t bytes); bool parse(); @@ -21,8 +26,8 @@ public: void cancel(); - static uint64_t toID(int32_t z, int32_t x, int32_t y, int32_t w = 0); - static vec4<int32_t> fromID(uint64_t id); + // static int64_t toID(int32_t z, int32_t x, int32_t y, int32_t w = 0); + // static vec4<int32_t> fromID(int64_t id); public: const int32_t z, x, y; @@ -31,6 +36,8 @@ public: linevertexbuffer lineVertex; private: + std::mutex mutex; + // Source data uint8_t *data; uint32_t bytes; diff --git a/include/llmr/platform/platform.hpp b/include/llmr/platform/platform.hpp index 69efb68064..e198f5331c 100644 --- a/include/llmr/platform/platform.hpp +++ b/include/llmr/platform/platform.hpp @@ -1,6 +1,8 @@ #ifndef LLMR_PLATFORM_IOS #define LLMR_PLATFORM_IOS +#include <memory> + namespace llmr { class tile; @@ -8,7 +10,7 @@ class tile; namespace platform { void restart(void *obj); -void request(void *obj, tile *tile); +void request(void *obj, std::shared_ptr<tile> tile); } diff --git a/include/llmr/renderer/painter.hpp b/include/llmr/renderer/painter.hpp index e01f6828a1..83a9171aba 100644 --- a/include/llmr/renderer/painter.hpp +++ b/include/llmr/renderer/painter.hpp @@ -19,13 +19,13 @@ public: void clear(); - void render(tile *tile); + void render(std::shared_ptr<tile> tile); void switchShader(Shader *shader, float matrix[16]); private: void setupShaders(); - void changeMatrix(tile *tile); + void changeMatrix(std::shared_ptr<tile> tile); public: diff --git a/include/llmr/util/vec2.hpp b/include/llmr/util/vec2.hpp index abc49e54bd..332f54f5f9 100644 --- a/include/llmr/util/vec2.hpp +++ b/include/llmr/util/vec2.hpp @@ -7,27 +7,27 @@ template <typename T = double> struct vec2 { T x, y; - // inline bool operator==(const vec2& rhs) const { - // return x == rhs.x && y == rhs.y; - // } + inline bool operator==(const vec2& rhs) const { + return x == rhs.x && y == rhs.y; + } }; template <typename T = double> struct vec3 { T x, y, z; - // inline bool operator==(const vec3& rhs) const { - // return x == rhs.x && y == rhs.y && z == rhs.z; - // } + inline bool operator==(const vec3& rhs) const { + return x == rhs.x && y == rhs.y && z == rhs.z; + } }; template <typename T = double> struct vec4 { T x, y, z, w; - // inline bool operator==(const vec4& rhs) const { - // return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; - // } + inline bool operator==(const vec4& rhs) const { + return x == rhs.x && y == rhs.y && z == rhs.z && w == rhs.w; + } }; diff --git a/macosx/main.mm b/macosx/main.mm index 20b6cc174a..23d75b4679 100644 --- a/macosx/main.mm +++ b/macosx/main.mm @@ -162,7 +162,7 @@ public: llmr::map *map; }; - +NSOperationQueue *queue = NULL; MapView *view; namespace llmr { @@ -172,23 +172,26 @@ void restart(void *) { view->dirty = true; } -void request(void *, tile *tile) { - fprintf(stderr, "request %d/%d/%d\n", tile->z, tile->x, tile->y); +void request(void *, tile::ptr tile) { + // fprintf(stderr, "request %d/%d/%d\n", tile->z, tile->x, tile->y); - fprintf(stderr, "requesting tile\n"); + // fprintf(stderr, "requesting tile\n"); // NSString *urlTemplate = @"http://api.tiles.mapbox.com/v3/mapbox.mapbox-streets-v4/%d/%d/%d.vector.pbf"; - NSString *urlTemplate = @"http://localhost:3333/gl/tiles/%d-%d-%d.vector.pbf"; + NSString *urlTemplate = @"http://localhost:3333/gl/tiles/plain/%d-%d-%d.vector.pbf"; NSString *urlString = [NSString stringWithFormat:urlTemplate, tile->z, tile->x, tile->y]; NSURL *url = [NSURL URLWithString:urlString]; - NSLog(@"Requesting %@", urlString); + // NSLog(@"Requesting %@", urlString); NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url]; - NSOperationQueue *queue = [[NSOperationQueue alloc] init]; + if (!queue) { + queue = [[NSOperationQueue alloc] init]; + } + [NSURLConnection sendAsynchronousRequest:urlRequest queue:queue @@ -196,12 +199,22 @@ void request(void *, tile *tile) { NSData * data, NSError * error) { if (error == nil) { - tile->setData((uint8_t *)[data bytes], [data length]); - if (tile->parse()) { + NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; + int code = [httpResponse statusCode]; + + if (code == 200) { + tile->setData((uint8_t *)[data bytes], [data length]); + if (tile->parse()) { + dispatch_async(dispatch_get_main_queue(), ^ { + view->map->tileLoaded(tile); + }); + return; + } + } else { + fprintf(stderr, "[%s] status code %d\n", [urlString UTF8String], code); dispatch_async(dispatch_get_main_queue(), ^ { - view->map->tileLoaded(tile); + view->map->tileFailed(tile); }); - return; } } diff --git a/src/geometry/linevertexbuffer.cpp b/src/geometry/linevertexbuffer.cpp index 04fd1c6c23..2086a0e865 100644 --- a/src/geometry/linevertexbuffer.cpp +++ b/src/geometry/linevertexbuffer.cpp @@ -9,6 +9,12 @@ linevertexbuffer::linevertexbuffer() : buffer(0) { } +linevertexbuffer::~linevertexbuffer() { + if (buffer != 0) { + glDeleteBuffers(1, &buffer); + } +} + void linevertexbuffer::addDegenerate() { array.push_back(32767); array.push_back(0); @@ -27,7 +33,7 @@ uint32_t linevertexbuffer::length() { void linevertexbuffer::bind() { if (buffer == 0) { glGenBuffers(1, &buffer); - fprintf(stderr, "new buffer id: %d\n", buffer); + // fprintf(stderr, "new buffer id: %d\n", buffer); glBindBuffer(GL_ARRAY_BUFFER, buffer); glBufferData(GL_ARRAY_BUFFER, array.size() * sizeof(uint16_t), array.data(), GL_STATIC_DRAW); } else { diff --git a/src/map/map.cpp b/src/map/map.cpp index 1fcf5d6636..f488899939 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -65,11 +65,14 @@ void map::updateTiles() { br.x = fmin(max_dim, ceil(fmax(box.tr.x, box.br.x))); br.y = fmin(max_dim, ceil(fmax(box.bl.y, box.br.y))); + typedef vec3<int32_t> tile_id; + // TODO: Discard tiles that are outside the viewport - std::vector<uint64_t> required; + std::vector<tile_id> required; for (int32_t y = tl.y; y < br.y; y++) { for (int32_t x = tl.x; x < br.x; x++) { - required.push_back(tile::toID(zoom, x, y)); + tile_id id; id.z = zoom; id.x = x; id.y = y; + required.push_back(id); } } @@ -79,17 +82,17 @@ void map::updateTiles() { // Remove tiles that we definitely don't need, i.e. tiles that are not on // the required list. - for (std::vector<tile *>::iterator it = tiles.begin(); it != tiles.end(); it++) { - tile *tile = *it; - uint64_t id = tile::toID(tile->z, tile->x, tile->y); - std::vector<uint64_t>::const_iterator required_it = std::find(required.begin(), required.end(), id); + for (std::vector<tile::ptr>::iterator it = tiles.begin(); it != tiles.end(); it++) { + tile::ptr& tile = *it; + tile_id id; id.z = tile->z; id.x = tile->x; id.y = tile->y; + std::vector<tile_id>::const_iterator required_it = std::find(required.begin(), required.end(), id); bool retain = required_it != required.end(); if (retain) { // We already have the tile; remove it from the list of required tiles. required.erase(required_it); } else { // We don't need this tile, so we can remove it entirely. - std::vector<class tile *>::iterator to_remove = it - 1; + std::vector<tile::ptr>::iterator to_remove = it - 1; tile->cancel(); tiles.erase(it); it = to_remove; @@ -98,9 +101,8 @@ void map::updateTiles() { // Required now only contains those tiles that are not yet in the list of // tiles, so we should add them all. - for (int64_t id : required) { - vec4<int32_t> tile_coord = tile::fromID(id); - tile *tile = new class tile(tile_coord.z, tile_coord.x, tile_coord.y); + for (tile_id& id : required) { + tile::ptr tile = std::make_shared<class tile>(id.z, id.x, id.y); tiles.push_back(tile); platform::request(this, tile); } @@ -109,7 +111,7 @@ void map::updateTiles() { bool map::render() { painter->clear(); - for (tile *tile : tiles) { + for (tile::ptr& tile : tiles) { // painter->viewport(); if (tile->loaded) { painter->render(tile); @@ -119,12 +121,12 @@ bool map::render() { return false; } -void map::tileLoaded(tile *tile) { +void map::tileLoaded(tile::ptr tile) { platform::restart(this); } -void map::tileFailed(tile *tile) { - fprintf(stderr, "[%8zx] tile failed to load %d/%d/%d\n", - std::hash<std::thread::id>()(std::this_thread::get_id()), - tile->z, tile->x, tile->y); +void map::tileFailed(tile::ptr tile) { + // fprintf(stderr, "[%8zx] tile failed to load %d/%d/%d\n", + // std::hash<std::thread::id>()(std::this_thread::get_id()), + // tile->z, tile->x, tile->y); } diff --git a/src/map/pbf.hpp b/src/map/pbf.hpp index b9ed95a1a0..41192d7b74 100644 --- a/src/map/pbf.hpp +++ b/src/map/pbf.hpp @@ -13,6 +13,12 @@ #include <string> // #include <cassert> +#define PBF_USE_SETJMP + +#ifdef PBF_USE_SETJMP +#include <csetjmp> +#endif + namespace llmr { struct pbf { @@ -29,9 +35,6 @@ struct pbf { // inline int64_t int64(); inline bool boolean(); - template <typename T, typename... Args> - inline T *message(const Args&... args); - inline void skip(); inline void skipValue(uint32_t val); inline void skipBytes(uint32_t bytes); @@ -40,6 +43,17 @@ struct pbf { const uint8_t *end; uint32_t value; uint32_t tag; + + enum error_code { + UNTERMINATED_VARINT = 1, + UNKNOWN_TYPE = 2, + END_OF_BUFFER = 3 + }; + + #ifdef PBF_USE_SETJMP + std::jmp_buf jump_buffer; + std::string msg; + #endif }; pbf::pbf(const unsigned char *data, uint32_t length) @@ -76,7 +90,10 @@ T pbf::varint() int bitpos; for (bitpos = 0; bitpos < 70 && (byte & 0x80); bitpos += 7) { if (data >= end) { - fprintf(stderr, "unterminated varint, unexpected end of buffer"); + #ifdef PBF_USE_SETJMP + msg = "unterminated varint, unexpected end of buffer"; + std::longjmp(jump_buffer, UNTERMINATED_VARINT); + #endif exit(1); } result |= ((T)(byte = *data) & 0x7F) << bitpos; @@ -84,7 +101,10 @@ T pbf::varint() data++; } if (bitpos == 70 && (byte & 0x80)) { - fprintf(stderr, "unterminated varint (too long)"); + #ifdef PBF_USE_SETJMP + msg = "unterminated varint (too long)"; + std::longjmp(jump_buffer, UNTERMINATED_VARINT); + #endif exit(1); } @@ -133,14 +153,13 @@ bool pbf::boolean() return *(bool *)(data - 1); } - -template <typename T, typename... Args> T *pbf::message(const Args&... args) -{ - uint32_t bytes = (uint32_t)varint(); - T *result = new T(data, bytes, args...); - skipBytes(bytes); - return result; -} +// template <typename T, typename... Args> T *pbf::message(const Args&... args) +// { +// uint32_t bytes = (uint32_t)varint(); +// T *result = new T(data, bytes, args...); +// skipBytes(bytes); +// return result; +// } void pbf::skip() { @@ -163,7 +182,12 @@ void pbf::skipValue(uint32_t val) skipBytes(4); break; default: - fprintf(stderr, "cannot skip unknown type %d", val & 0x7); + char text[32]; + snprintf(text, 32, "cannot skip unknown type %d", val & 0x7); + #ifdef PBF_USE_SETJMP + msg = text; + std::longjmp(jump_buffer, UNKNOWN_TYPE); + #endif exit(1); } } @@ -172,7 +196,10 @@ void pbf::skipBytes(uint32_t bytes) { data += bytes; if (data > end) { - fprintf(stderr, "unexpected end of buffer"); + #ifdef PBF_USE_SETJMP + msg = "unexpected end of buffer"; + std::longjmp(jump_buffer, END_OF_BUFFER); + #endif exit(1); } } diff --git a/src/map/tile.cpp b/src/map/tile.cpp index c04392af3a..ab9f2fe03b 100644 --- a/src/map/tile.cpp +++ b/src/map/tile.cpp @@ -12,25 +12,27 @@ using namespace llmr; -uint64_t tile::toID(int32_t z, int32_t x, int32_t y, int32_t w) { - w *= 2; - if (w < 0) w = w * -1 -1; - int32_t dim = 1 << z; - return ((dim * dim * w + dim * y + x) * 32) + z; -} - -vec4<int32_t> tile::fromID(uint64_t id) { - vec4<int32_t> coord; - coord.z = id % 32; - int32_t dim = 1 << coord.z; - int32_t xy = ((id - coord.z) / 32); - coord.x = xy % dim; - coord.y = ((xy - coord.x) / dim) % dim; - coord.w = floor(xy / (dim * dim)); - if (coord.w % 2 != 0) coord.w = coord.w * -1 -1; - coord.w /= 2; - return coord; -}; +// int64_t tile::toID(int32_t z, int32_t x, int32_t y, int32_t w) { +// w *= 2; +// if (w < 0) w = w * -1 -1; +// int32_t dim = 1 << z; +// return ((dim * dim * w + dim * y + x) * 32) + z; +// } + +// vec4<int32_t> tile::fromID(int64_t id) { +// vec4<int32_t> coord; +// coord.z = id % 32; +// int32_t dim = 1 << coord.z; +// int64_t xy = ((id - coord.z) / 32); +// coord.x = xy % dim; +// coord.y = ((xy - coord.x) / dim) % dim; +// coord.w = floor(xy / (dim * dim)); +// if (coord.w % 2 != 0) coord.w = coord.w * -1 -1; +// coord.w /= 2; + +// fprintf(stderr, "tile: %d/%d/%d/%d\n", coord.z, coord.x, coord.y, coord.w); +// return coord; +// }; tile::tile(int32_t z, int32_t x, int32_t y) : z(z), @@ -42,6 +44,13 @@ tile::tile(int32_t z, int32_t x, int32_t y) bytes(0) { } +tile::~tile() { + fprintf(stderr, "[%p] deleting tile %d/%d/%d\n", this, z, x, y); + if (this->data) { + free(this->data); + } +} + void tile::setData(uint8_t *data, uint32_t bytes) { this->data = (uint8_t *)malloc(bytes); this->bytes = bytes; @@ -50,12 +59,11 @@ void tile::setData(uint8_t *data, uint32_t bytes) { void tile::cancel() { + std::lock_guard<std::mutex> lock(mutex); + // TODO: thread safety if (!cancelled) { cancelled = true; - if (loaded) { - delete this; - } } else { assert((!"logic error? multiple cancelleations")); } @@ -63,14 +71,24 @@ void tile::cancel() bool tile::parse() { - if (cancelled) { - delete this; - return false; + { + std::lock_guard<std::mutex> lock(mutex); + if (cancelled) { + return false; + } } - fprintf(stderr, "[%p] parsing tile...\n", this); + // fprintf(stderr, "[%p] parsing tile [%d/%d/%d]...\n", this, z, x, y); pbf tile(data, bytes); + + int code = setjmp(tile.jump_buffer); + if (code > 0) { + fprintf(stderr, "[%p] parsing tile [%d/%d/%d]... failed: %s\n", this, z, x, y, tile.msg.c_str()); + cancel(); + return false; + } + while (tile.next()) { if (tile.tag == 3) { // layer uint32_t bytes = (uint32_t)tile.varint(); @@ -81,11 +99,13 @@ bool tile::parse() } } - fprintf(stderr, "[%p] parsing tile...done\n", this); + // fprintf(stderr, "[%p] parsing tile [%d/%d/%d]... done\n", this, z, x, y); - if (cancelled) { - delete this; - return false; + { + std::lock_guard<std::mutex> lock(mutex); + if (cancelled) { + return false; + } } loaded = true; diff --git a/src/map/transform.cpp b/src/map/transform.cpp index e31fad4233..6c5f902c86 100644 --- a/src/map/transform.cpp +++ b/src/map/transform.cpp @@ -52,8 +52,6 @@ void transform::scaleBy(double ds, double cx, double cy) { scale *= ds; x = (x * ds) + fx; y = (y * ds) + fy; - - fprintf(stderr, "scale: %f, %f, %f\n", scale, x, y); } diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 656d1fd645..a7ee1f034a 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -79,7 +79,7 @@ void painter::teardown() { } -void painter::changeMatrix(tile *tile) { +void painter::changeMatrix(std::shared_ptr<tile> tile) { assert(transform); // Initialize projection matrix @@ -97,7 +97,7 @@ void painter::clear() { glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } -void painter::render(tile *tile) { +void painter::render(std::shared_ptr<tile> tile) { changeMatrix(tile); glDisable(GL_STENCIL_TEST); |