summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2015-06-04 16:36:37 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-07-01 15:21:08 -0700
commit29a2cd908f6ed3d62ecfd113457074d1524d4f49 (patch)
treed7b5bee7a60f651c835786b4dcebdb98448ee99a
parent7e71145a89f0377736312c3b818a41ffb25bdf9a (diff)
downloadqtlocation-mapboxgl-29a2cd908f6ed3d62ecfd113457074d1524d4f49.tar.gz
Introduce TileWorker
-rw-r--r--src/mbgl/map/live_tile_data.cpp55
-rw-r--r--src/mbgl/map/live_tile_data.hpp2
-rw-r--r--src/mbgl/map/tile_parser.cpp4
-rw-r--r--src/mbgl/map/tile_parser.hpp6
-rw-r--r--src/mbgl/map/tile_worker.cpp78
-rw-r--r--src/mbgl/map/tile_worker.hpp75
-rw-r--r--src/mbgl/map/vector_tile_data.cpp116
-rw-r--r--src/mbgl/map/vector_tile_data.hpp50
8 files changed, 239 insertions, 147 deletions
diff --git a/src/mbgl/map/live_tile_data.cpp b/src/mbgl/map/live_tile_data.cpp
index 4a90ea786c..74d939f35a 100644
--- a/src/mbgl/map/live_tile_data.cpp
+++ b/src/mbgl/map/live_tile_data.cpp
@@ -1,10 +1,10 @@
#include <mbgl/map/annotation.hpp>
#include <mbgl/map/live_tile_data.hpp>
#include <mbgl/map/live_tile.hpp>
-#include <mbgl/map/tile_parser.hpp>
-#include <mbgl/map/source.hpp>
-#include <mbgl/map/vector_tile.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/worker.hpp>
+#include <mbgl/util/work_request.hpp>
+
+#include <sstream>
using namespace mbgl;
@@ -26,28 +26,43 @@ LiveTileData::~LiveTileData() {
cancel();
}
-void LiveTileData::parse() {
- if (getState() != State::loaded) {
- return;
+bool LiveTileData::reparse(Worker&, std::function<void()> callback) {
+ if (!mayStartParsing()) {
+ return false;
}
- const LiveTile* tile = annotationManager.getTile(id);
+ workRequest = worker.send([this] {
+ if (getState() != State::loaded) {
+ return;
+ }
+
+ const LiveTile* tile = annotationManager.getTile(id);
+
+ if (!tile) {
+ setState(State::parsed);
+ return;
+ }
+
+ TileParseResult result;
- if (tile) {
try {
- // 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.
- TileParser parser(*tile, *this, style);
- parser.parse();
+ result = workerData.parse(*tile);
} catch (const std::exception& ex) {
- Log::Error(Event::ParseTile, "Live-parsing [%d/%d/%d] failed: %s", id.z, id.x, id.y, ex.what());
- setState(State::obsolete);
+ std::stringstream message;
+ message << "Failed to parse [" << int(id.sourceZ) << "/" << id.x << "/" << id.y << "]: " << ex.what();
+ result = message.str();
+ }
+
+ if (getState() == TileData::State::obsolete) {
return;
+ } else if (result.is<State>()) {
+ setState(result.get<State>());
+ } else {
+ setError(result.get<std::string>());
}
- }
- if (getState() != State::obsolete) {
- setState(State::parsed);
- }
+ endParsing();
+ }, callback);
+
+ return true;
}
diff --git a/src/mbgl/map/live_tile_data.hpp b/src/mbgl/map/live_tile_data.hpp
index f4f5412089..c837057e82 100644
--- a/src/mbgl/map/live_tile_data.hpp
+++ b/src/mbgl/map/live_tile_data.hpp
@@ -17,7 +17,7 @@ public:
bool collisionDebug_);
~LiveTileData();
- void parse() override;
+ bool reparse(Worker&, std::function<void ()> callback) override;
private:
AnnotationManager& annotationManager;
diff --git a/src/mbgl/map/tile_parser.cpp b/src/mbgl/map/tile_parser.cpp
index 56b34acdd2..a88084391f 100644
--- a/src/mbgl/map/tile_parser.cpp
+++ b/src/mbgl/map/tile_parser.cpp
@@ -20,7 +20,7 @@ namespace mbgl {
TileParser::~TileParser() = default;
TileParser::TileParser(const GeometryTile& geometryTile_,
- VectorTileData& tile_,
+ TileWorker& tile_,
Style& style_)
: geometryTile(geometryTile_),
tile(tile_),
@@ -98,7 +98,7 @@ void applyLayoutProperty(PropertyKey key, const ClassProperties &classProperties
std::unique_ptr<Bucket> TileParser::createBucket(const StyleBucket &bucketDesc) {
// Skip this bucket if we are to not render this
- if (tile.id.z < std::floor(bucketDesc.min_zoom) && std::floor(bucketDesc.min_zoom) < tile.source.max_zoom) return nullptr;
+ if (tile.id.z < std::floor(bucketDesc.min_zoom) && std::floor(bucketDesc.min_zoom) < tile.maxZoom) return nullptr;
if (tile.id.z >= std::ceil(bucketDesc.max_zoom)) return nullptr;
if (bucketDesc.visibility == mbgl::VisibilityType::None) return nullptr;
diff --git a/src/mbgl/map/tile_parser.hpp b/src/mbgl/map/tile_parser.hpp
index b716721a5d..63c1fd72aa 100644
--- a/src/mbgl/map/tile_parser.hpp
+++ b/src/mbgl/map/tile_parser.hpp
@@ -24,11 +24,11 @@ class StyleLayoutFill;
class StyleLayoutRaster;
class StyleLayoutLine;
class StyleLayoutSymbol;
-class VectorTileData;
+class TileWorker;
class TileParser : private util::noncopyable {
public:
- TileParser(const GeometryTile&, VectorTileData&, Style&);
+ TileParser(const GeometryTile&, TileWorker&, Style&);
~TileParser();
public:
@@ -49,7 +49,7 @@ private:
void addBucketGeometries(Bucket&, const GeometryTileLayer&, const FilterExpression&);
const GeometryTile& geometryTile;
- VectorTileData& tile;
+ TileWorker& tile;
// Cross-thread shared data.
Style& style;
diff --git a/src/mbgl/map/tile_worker.cpp b/src/mbgl/map/tile_worker.cpp
new file mode 100644
index 0000000000..1991ab1885
--- /dev/null
+++ b/src/mbgl/map/tile_worker.cpp
@@ -0,0 +1,78 @@
+#include <mbgl/text/collision_tile.hpp>
+#include <mbgl/map/tile_worker.hpp>
+#include <mbgl/map/tile_parser.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/style/style_layer.hpp>
+#include <mbgl/geometry/glyph_atlas.hpp>
+
+using namespace mbgl;
+
+TileWorker::TileWorker(const TileID& id_,
+ Style& style_,
+ const uint16_t maxZoom_,
+ const std::atomic<TileData::State>& state_,
+ std::unique_ptr<CollisionTile> collision_)
+ : id(id_),
+ style(style_),
+ maxZoom(maxZoom_),
+ state(state_),
+ collision(std::move(collision_)) {
+}
+
+TileWorker::~TileWorker() {
+ style.glyphAtlas->removeGlyphs(reinterpret_cast<uintptr_t>(this));
+}
+
+void TileWorker::setBucket(const StyleLayer& layer, std::unique_ptr<Bucket> bucket) {
+ assert(layer.bucket);
+
+ std::lock_guard<std::mutex> lock(bucketsMutex);
+
+ if (buckets.find(layer.bucket->name) != buckets.end()) {
+ return;
+ }
+
+ buckets[layer.bucket->name] = std::move(bucket);
+}
+
+Bucket* TileWorker::getBucket(const StyleLayer& layer) const {
+ std::lock_guard<std::mutex> lock(bucketsMutex);
+
+ const auto it = buckets.find(layer.bucket->name);
+ if (it == buckets.end()) {
+ return nullptr;
+ }
+
+ assert(it->second);
+ return it->second.get();
+}
+
+size_t TileWorker::countBuckets() const {
+ std::lock_guard<std::mutex> lock(bucketsMutex);
+ return buckets.size();
+}
+
+TileParseResult TileWorker::parse(const GeometryTile& geometryTile) {
+ // 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.
+ TileParser parser(geometryTile, *this, style);
+ parser.parse();
+
+ if (parser.isPartialParse()) {
+ return TileData::State::partial;
+ } else {
+ return TileData::State::parsed;
+ }
+}
+
+void TileWorker::redoPlacement(float angle, bool collisionDebug) {
+ collision->reset(angle, 0);
+ collision->setDebug(collisionDebug);
+ for (const auto& layer_desc : style.layers) {
+ auto bucket = getBucket(*layer_desc);
+ if (bucket) {
+ bucket->placeFeatures();
+ }
+ }
+}
diff --git a/src/mbgl/map/tile_worker.hpp b/src/mbgl/map/tile_worker.hpp
new file mode 100644
index 0000000000..420b0bf9f2
--- /dev/null
+++ b/src/mbgl/map/tile_worker.hpp
@@ -0,0 +1,75 @@
+#ifndef MBGL_MAP_TILE_WORKER
+#define MBGL_MAP_TILE_WORKER
+
+#include <mbgl/util/variant.hpp>
+#include <mbgl/map/tile_data.hpp>
+#include <mbgl/geometry/elements_buffer.hpp>
+#include <mbgl/geometry/fill_buffer.hpp>
+#include <mbgl/geometry/line_buffer.hpp>
+#include <mbgl/util/noncopyable.hpp>
+
+#include <memory>
+#include <mutex>
+#include <unordered_map>
+
+namespace mbgl {
+
+class CollisionTile;
+class GeometryTile;
+class Style;
+class Bucket;
+
+using TileParseResult = mapbox::util::variant<
+ TileData::State, // success
+ std::string>; // error
+
+class TileWorker : public util::noncopyable {
+public:
+ TileWorker(const TileID&,
+ Style&,
+ const uint16_t maxZoom,
+ const std::atomic<TileData::State>&,
+ std::unique_ptr<CollisionTile>);
+ ~TileWorker();
+
+ void setBucket(const StyleLayer&, std::unique_ptr<Bucket>);
+ Bucket* getBucket(const StyleLayer&) const;
+ size_t countBuckets() const;
+
+ inline TileData::State getState() const {
+ return state;
+ }
+
+ inline CollisionTile* getCollision() const {
+ return collision.get();
+ }
+
+ TileParseResult parse(const GeometryTile&);
+ void redoPlacement(float angle, bool collisionDebug);
+
+ const TileID id;
+ Style& style;
+ const uint16_t maxZoom;
+ const std::atomic<TileData::State>& state;
+
+ FillVertexBuffer fillVertexBuffer;
+ LineVertexBuffer lineVertexBuffer;
+
+ TriangleElementsBuffer triangleElementsBuffer;
+ LineElementsBuffer lineElementsBuffer;
+
+ std::unique_ptr<CollisionTile> collision;
+
+ // Contains all the Bucket objects for the tile. Buckets are render
+ // objects and they get added to this std::map<> by the workers doing
+ // the actual tile parsing as they get processed. Tiles partially
+ // parsed can get new buckets at any moment but are also fit for
+ // rendering. That said, access to this list needs locking unless
+ // the tile is completely parsed.
+ std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+ mutable std::mutex bucketsMutex;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/map/vector_tile_data.cpp b/src/mbgl/map/vector_tile_data.cpp
index 34cfe4311f..f485a24958 100644
--- a/src/mbgl/map/vector_tile_data.cpp
+++ b/src/mbgl/map/vector_tile_data.cpp
@@ -1,10 +1,8 @@
#include <mbgl/map/vector_tile_data.hpp>
-#include <mbgl/map/tile_parser.hpp>
#include <mbgl/style/style_layer.hpp>
#include <mbgl/style/style_bucket.hpp>
#include <mbgl/map/source.hpp>
-#include <mbgl/geometry/glyph_atlas.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/map/vector_tile.hpp>
#include <mbgl/text/collision_tile.hpp>
#include <mbgl/util/pbf.hpp>
#include <mbgl/storage/resource.hpp>
@@ -22,8 +20,14 @@ VectorTileData::VectorTileData(const TileID& id_,
float angle,
bool collisionDebug)
: TileData(id_, source_),
- style(style_),
- collision(std::make_unique<CollisionTile>(id_.z, 4096, source_.tile_size * id.overscaling, angle, collisionDebug)),
+ worker(style_.workers),
+ workerData(id_,
+ style_,
+ source.max_zoom,
+ state,
+ std::make_unique<CollisionTile>(id_.z, 4096,
+ source_.tile_size * id.overscaling,
+ angle, collisionDebug)),
lastAngle(angle),
currentAngle(angle) {
}
@@ -32,17 +36,16 @@ VectorTileData::~VectorTileData() {
// Cancel in most derived class destructor so that worker tasks are joined before
// any member data goes away.
cancel();
- style.glyphAtlas->removeGlyphs(reinterpret_cast<uintptr_t>(this));
}
-void VectorTileData::request(Worker& worker,
+void VectorTileData::request(Worker&,
float pixelRatio,
const std::function<void()>& callback) {
std::string url = source.tileURL(id, pixelRatio);
state = State::loading;
FileSource* fs = util::ThreadContext::getFileSource();
- req = fs->request({ Resource::Kind::Tile, url }, util::RunLoop::current.get()->get(), [url, callback, &worker, this](const Response &res) {
+ req = fs->request({ Resource::Kind::Tile, url }, util::RunLoop::current.get()->get(), [url, callback, this](const Response &res) {
req = nullptr;
if (res.status != Response::Successful) {
@@ -56,89 +59,62 @@ void VectorTileData::request(Worker& worker,
state = State::loaded;
data = res.data;
- // Schedule tile parsing in another thread
reparse(worker, callback);
});
}
-bool VectorTileData::reparse(Worker& worker, std::function<void()> callback) {
+bool VectorTileData::reparse(Worker&, std::function<void()> callback) {
if (!mayStartParsing()) {
return false;
}
- workRequest = worker.send([this] { parse(); endParsing(); }, callback);
- return true;
-}
-
-void VectorTileData::parse() {
- if (getState() != State::loaded && getState() != State::partial) {
- return;
- }
+ workRequest = worker.send([this] {
+ if (getState() != TileData::State::loaded && getState() != TileData::State::partial) {
+ return;
+ }
- try {
- // 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.
- VectorTile vectorTile(pbf((const uint8_t *)data.data(), data.size()));
- const VectorTile* vt = &vectorTile;
- TileParser parser(*vt, *this, style);
- parser.parse();
+ TileParseResult result;
- if (getState() == State::obsolete) {
- return;
+ try {
+ VectorTile vectorTile(pbf((const uint8_t *)data.data(), data.size()));
+ result = workerData.parse(vectorTile);
+ } catch (const std::exception& ex) {
+ std::stringstream message;
+ message << "Failed to parse [" << int(id.sourceZ) << "/" << id.x << "/" << id.y << "]: " << ex.what();
+ result = message.str();
}
- if (parser.isPartialParse()) {
- setState(State::partial);
+ if (getState() == TileData::State::obsolete) {
+ return;
+ } else if (result.is<State>()) {
+ setState(result.get<State>());
} else {
- setState(State::parsed);
+ setError(result.get<std::string>());
}
- } catch (const std::exception& ex) {
- std::stringstream message;
- message << "Failed to parse [" << int(id.sourceZ) << "/" << id.x << "/" << id.y << "]: " << ex.what();
- setError(message.str());
- }
-}
-Bucket* VectorTileData::getBucket(StyleLayer const& layer) {
- if (!isReady() || !layer.bucket) {
- return nullptr;
- }
+ endParsing();
+ }, callback);
- std::lock_guard<std::mutex> lock(bucketsMutex);
+ return true;
+}
- const auto it = buckets.find(layer.bucket->name);
- if (it == buckets.end()) {
+Bucket* VectorTileData::getBucket(const StyleLayer& layer) {
+ if (!isReady() || !layer.bucket) {
return nullptr;
}
- assert(it->second);
- return it->second.get();
+ return workerData.getBucket(layer);
}
size_t VectorTileData::countBuckets() const {
- std::lock_guard<std::mutex> lock(bucketsMutex);
-
- return buckets.size();
-}
-
-void VectorTileData::setBucket(StyleLayer const& layer, std::unique_ptr<Bucket> bucket) {
- assert(layer.bucket);
-
- std::lock_guard<std::mutex> lock(bucketsMutex);
-
- if (buckets.find(layer.bucket->name) != buckets.end()) {
- return;
- }
-
- buckets[layer.bucket->name] = std::move(bucket);
+ return workerData.countBuckets();
}
void VectorTileData::setState(const State& state_) {
TileData::setState(state_);
if (isImmutable()) {
- collision->reset(0, 0);
+ workerData.collision->reset(0, 0);
}
}
@@ -158,24 +134,12 @@ void VectorTileData::redoPlacement(float angle, bool collisionDebug) {
currentCollisionDebug = collisionDebug;
auto callback = std::bind(&VectorTileData::endRedoPlacement, this);
- workRequest = style.workers.send([this, angle, collisionDebug] { workerRedoPlacement(angle, collisionDebug); }, callback);
-
- }
-}
-
-void VectorTileData::workerRedoPlacement(float angle, bool collisionDebug) {
- collision->reset(angle, 0);
- collision->setDebug(collisionDebug);
- for (const auto& layer_desc : style.layers) {
- auto bucket = getBucket(*layer_desc);
- if (bucket) {
- bucket->placeFeatures();
- }
+ workRequest = worker.send([this, angle, collisionDebug] { workerData.redoPlacement(angle, collisionDebug); }, callback);
}
}
void VectorTileData::endRedoPlacement() {
- for (const auto& layer_desc : style.layers) {
+ for (const auto& layer_desc : workerData.style.layers) {
auto bucket = getBucket(*layer_desc);
if (bucket) {
bucket->swapRenderData();
diff --git a/src/mbgl/map/vector_tile_data.hpp b/src/mbgl/map/vector_tile_data.hpp
index faddb1dc7d..4cfe4e12ae 100644
--- a/src/mbgl/map/vector_tile_data.hpp
+++ b/src/mbgl/map/vector_tile_data.hpp
@@ -2,31 +2,16 @@
#define MBGL_MAP_VECTOR_TILE_DATA
#include <mbgl/map/tile_data.hpp>
-#include <mbgl/geometry/elements_buffer.hpp>
-#include <mbgl/geometry/fill_buffer.hpp>
-#include <mbgl/geometry/icon_buffer.hpp>
-#include <mbgl/geometry/line_buffer.hpp>
-#include <mbgl/geometry/text_buffer.hpp>
-#include <mbgl/geometry/collision_box_buffer.hpp>
-
-#include <iosfwd>
-#include <memory>
-#include <mutex>
-#include <unordered_map>
+#include <mbgl/map/tile_worker.hpp>
namespace mbgl {
class Bucket;
-class CollisionTile;
-class Painter;
class SourceInfo;
class StyleLayer;
-class TileParser;
class Style;
class VectorTileData : public TileData {
- friend class TileParser;
-
public:
VectorTileData(const TileID&,
Style&,
@@ -35,18 +20,11 @@ public:
bool collisionDebug_);
~VectorTileData();
- virtual void parse();
void redoPlacement(float angle, bool collisionDebug) override;
- virtual Bucket* getBucket(StyleLayer const &layer_desc) override;
-
- size_t countBuckets() const;
- void setBucket(StyleLayer const &layer_desc, std::unique_ptr<Bucket> bucket);
-
void setState(const State& state) override;
- inline CollisionTile* getCollision() const {
- return collision.get();
- }
+ Bucket* getBucket(const StyleLayer&) override;
+ size_t countBuckets() const;
void request(Worker&,
float pixelRatio,
@@ -57,34 +35,16 @@ public:
protected:
void redoPlacement();
- // Holds the actual geometries in this tile.
- FillVertexBuffer fillVertexBuffer;
- LineVertexBuffer lineVertexBuffer;
-
- TriangleElementsBuffer triangleElementsBuffer;
- LineElementsBuffer lineElementsBuffer;
-
- Style& style;
+ Worker& worker;
+ TileWorker workerData;
private:
- // Contains all the Bucket objects for the tile. Buckets are render
- // objects and they get added to this std::map<> by the workers doing
- // the actual tile parsing as they get processed. Tiles partially
- // parsed can get new buckets at any moment but are also fit for
- // rendering. That said, access to this list needs locking unless
- // the tile is completely parsed.
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
- mutable std::mutex bucketsMutex;
-
- std::unique_ptr<CollisionTile> collision;
-
float lastAngle = 0;
float currentAngle;
bool lastCollisionDebug = 0;
bool currentCollisionDebug = 0;
bool redoingPlacement = false;
void endRedoPlacement();
- void workerRedoPlacement(float angle, bool collisionDebug);
};
}