Introduce TileWorker

This commit is contained in:
John Firebaugh
2015-06-04 16:36:37 -07:00
parent 7e71145a89
commit 29a2cd908f
8 changed files with 244 additions and 152 deletions

View File

@@ -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;
}
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();
if (getState() == State::obsolete) {
workRequest = worker.send([this] {
if (getState() != TileData::State::loaded && getState() != TileData::State::partial) {
return;
}
if (parser.isPartialParse()) {
setState(State::partial);
} else {
setState(State::parsed);
TileParseResult result;
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();
}
} catch (const std::exception& ex) {
std::stringstream message;
message << "Failed to parse [" << int(id.sourceZ) << "/" << id.x << "/" << id.y << "]: " << ex.what();
setError(message.str());
}
if (getState() == TileData::State::obsolete) {
return;
} else if (result.is<State>()) {
setState(result.get<State>());
} else {
setError(result.get<std::string>());
}
endParsing();
}, callback);
return true;
}
Bucket* VectorTileData::getBucket(StyleLayer const& layer) {
Bucket* VectorTileData::getBucket(const StyleLayer& layer) {
if (!isReady() || !layer.bucket) {
return nullptr;
}
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();
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();