[core] restructure TileSource construction and callbacks
This commit is contained in:
@@ -25,7 +25,7 @@
|
||||
#include <mbgl/tile/vector_tile_source.hpp>
|
||||
#include <mbgl/tile/geojson_tile_source.hpp>
|
||||
#include <mbgl/tile/annotation_tile_source.hpp>
|
||||
#include <mbgl/tile/raster_tile_source.hpp>
|
||||
#include <mbgl/tile/image_tile_source.hpp>
|
||||
|
||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||
#include <mbgl/tile/raster_tile_data.hpp>
|
||||
@@ -193,8 +193,7 @@ const std::map<UnwrappedTileID, Tile>& Source::getTiles() const {
|
||||
|
||||
std::unique_ptr<TileData> Source::createTile(const OverscaledTileID& overscaledTileID,
|
||||
const UpdateParameters& parameters) {
|
||||
std::unique_ptr<TileData> data = cache.get(overscaledTileID);
|
||||
if (data) {
|
||||
if (auto data = cache.get(overscaledTileID)) {
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -207,33 +206,40 @@ std::unique_ptr<TileData> Source::createTile(const OverscaledTileID& overscaledT
|
||||
const auto resource = Resource::tile(
|
||||
tileset->tiles.at(0), parameters.pixelRatio, overscaledTileID.canonical.x,
|
||||
overscaledTileID.canonical.y, overscaledTileID.canonical.z);
|
||||
auto monitor = std::make_unique<RasterTileSource>(resource, parameters.fileSource);
|
||||
data =
|
||||
std::make_unique<RasterTileData>(overscaledTileID, std::move(monitor),
|
||||
parameters.texturePool, parameters.worker, callback);
|
||||
} else {
|
||||
std::unique_ptr<GeometryTileSource> monitor;
|
||||
auto data = std::make_unique<RasterTileData>(overscaledTileID, parameters.texturePool,
|
||||
parameters.worker, callback);
|
||||
data->setTileSource(
|
||||
std::make_unique<ImageTileSource>(*data, resource, parameters.fileSource));
|
||||
|
||||
// Need a std::move here to create a std::unique_ptr<TileData> from
|
||||
// std::unique_ptr<GeometryTileData>.
|
||||
return std::move(data);
|
||||
} else {
|
||||
auto data = std::make_unique<GeometryTileData>(overscaledTileID, id, parameters.style,
|
||||
parameters.mode, callback);
|
||||
if (type == SourceType::Vector) {
|
||||
assert(!tileset->tiles.empty());
|
||||
const auto resource = Resource::tile(
|
||||
tileset->tiles.at(0), parameters.pixelRatio, overscaledTileID.canonical.x,
|
||||
overscaledTileID.canonical.y, overscaledTileID.canonical.z);
|
||||
monitor = std::make_unique<VectorTileSource>(resource, parameters.fileSource);
|
||||
data->setTileSource(
|
||||
std::make_unique<VectorTileSource>(*data, resource, parameters.fileSource));
|
||||
} else if (type == SourceType::Annotations) {
|
||||
monitor = std::make_unique<AnnotationTileSource>(overscaledTileID, parameters.annotationManager);
|
||||
data->setTileSource(std::make_unique<AnnotationTileSource>(
|
||||
*data, overscaledTileID, parameters.annotationManager));
|
||||
} else if (type == SourceType::GeoJSON) {
|
||||
monitor = std::make_unique<GeoJSONTileSource>(geojsonvt.get(), overscaledTileID);
|
||||
data->setTileSource(
|
||||
std::make_unique<GeoJSONTileSource>(*data, geojsonvt.get(), overscaledTileID));
|
||||
} else {
|
||||
Log::Warning(Event::Style, "Source type '%s' is not implemented", SourceTypeClass(type).c_str());
|
||||
Log::Warning(Event::Style, "Source type '%s' is not implemented",
|
||||
SourceTypeClass(type).c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
data = std::make_unique<GeometryTileData>(overscaledTileID, std::move(monitor), id,
|
||||
parameters.style, parameters.mode, callback);
|
||||
// Need a std::move here to create a std::unique_ptr<TileData> from
|
||||
// std::unique_ptr<GeometryTileData>.
|
||||
return std::move(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
TileData* Source::getTileData(const OverscaledTileID& overscaledTileID) const {
|
||||
@@ -322,13 +328,9 @@ bool Source::update(const UpdateParameters& parameters) {
|
||||
}
|
||||
|
||||
for (auto& pair : tileDataMap) {
|
||||
const auto& dataTileID = pair.first;
|
||||
auto tileData = pair.second.get();
|
||||
if (parameters.shouldReparsePartialTiles && tileData->isIncomplete()) {
|
||||
auto callback = std::bind(&Source::tileLoadingCallback, this, dataTileID,
|
||||
std::placeholders::_1, false);
|
||||
|
||||
if (!tileData->parsePending(callback)) {
|
||||
if (!tileData->parsePending()) {
|
||||
allTilesUpdated = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,28 +1,24 @@
|
||||
#include <mbgl/tile/annotation_tile_source.hpp>
|
||||
#include <mbgl/tile/geometry_tile.hpp>
|
||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||
#include <mbgl/annotation/annotation_manager.hpp>
|
||||
#include <mbgl/util/async_request.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
AnnotationTileSource::AnnotationTileSource(const OverscaledTileID& tileID_,
|
||||
AnnotationManager& annotationManager_)
|
||||
: tileID(tileID_), annotationManager(annotationManager_) {
|
||||
AnnotationTileSource::AnnotationTileSource(GeometryTileData& tileData_,
|
||||
const OverscaledTileID& tileID_,
|
||||
AnnotationManager& annotationManager_)
|
||||
: GeometryTileSource(tileData_), tileID(tileID_), annotationManager(annotationManager_) {
|
||||
annotationManager.addTileSource(*this);
|
||||
}
|
||||
|
||||
AnnotationTileSource::~AnnotationTileSource() {
|
||||
annotationManager.removeTileSource(*this);
|
||||
}
|
||||
|
||||
std::unique_ptr<AsyncRequest>
|
||||
AnnotationTileSource::monitorTile(const GeometryTileSource::Callback& callback_) {
|
||||
callback = callback_;
|
||||
annotationManager.addTileSource(*this);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AnnotationTileSource::update(std::unique_ptr<GeometryTile> tile) {
|
||||
callback(nullptr, std::move(tile), {}, {});
|
||||
tileData.setData(nullptr, std::move(tile), {}, {});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -8,20 +8,19 @@
|
||||
namespace mbgl {
|
||||
|
||||
class AnnotationManager;
|
||||
class GeometryTile;
|
||||
|
||||
class AnnotationTileSource : public GeometryTileSource {
|
||||
public:
|
||||
AnnotationTileSource(const OverscaledTileID&, AnnotationManager&);
|
||||
AnnotationTileSource(GeometryTileData&, const OverscaledTileID&, AnnotationManager&);
|
||||
~AnnotationTileSource();
|
||||
|
||||
void update(std::unique_ptr<GeometryTile>);
|
||||
std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileSource::Callback&) override;
|
||||
|
||||
OverscaledTileID tileID;
|
||||
|
||||
private:
|
||||
AnnotationManager& annotationManager;
|
||||
GeometryTileSource::Callback callback;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <mbgl/tile/geojson_tile_source.hpp>
|
||||
#include <mbgl/tile/geojson_tile.hpp>
|
||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||
|
||||
#include <mbgl/util/async_request.hpp>
|
||||
|
||||
@@ -7,9 +8,11 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
GeoJSONTileSource::GeoJSONTileSource(mapbox::geojsonvt::GeoJSONVT* geojsonvt_,
|
||||
GeoJSONTileSource::GeoJSONTileSource(GeometryTileData& tileData_,
|
||||
mapbox::geojsonvt::GeoJSONVT* geojsonvt_,
|
||||
const OverscaledTileID& id)
|
||||
: tileID(id), geojsonvt(geojsonvt_) {
|
||||
: GeometryTileSource(tileData_), tileID(id), geojsonvt(geojsonvt_) {
|
||||
update();
|
||||
}
|
||||
|
||||
GeoJSONTileSource::~GeoJSONTileSource() = default;
|
||||
@@ -89,15 +92,8 @@ void GeoJSONTileSource::update() {
|
||||
if (geojsonvt) {
|
||||
auto tile = convertTile(
|
||||
geojsonvt->getTile(tileID.canonical.z, tileID.canonical.x, tileID.canonical.y));
|
||||
callback(nullptr, std::move(tile), {}, {});
|
||||
tileData.setData(nullptr, std::move(tile), {}, {});
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<AsyncRequest>
|
||||
GeoJSONTileSource::monitorTile(const GeometryTileSource::Callback& cb) {
|
||||
callback = cb;
|
||||
update();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -16,11 +16,9 @@ namespace mbgl {
|
||||
|
||||
class GeoJSONTileSource : public GeometryTileSource {
|
||||
public:
|
||||
GeoJSONTileSource(mapbox::geojsonvt::GeoJSONVT*, const OverscaledTileID&);
|
||||
GeoJSONTileSource(GeometryTileData&, mapbox::geojsonvt::GeoJSONVT*, const OverscaledTileID&);
|
||||
virtual ~GeoJSONTileSource();
|
||||
|
||||
std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileSource::Callback&) override;
|
||||
|
||||
void setGeoJSONVT(mapbox::geojsonvt::GeoJSONVT*);
|
||||
|
||||
private:
|
||||
@@ -31,7 +29,6 @@ public:
|
||||
|
||||
private:
|
||||
mapbox::geojsonvt::GeoJSONVT* geojsonvt = nullptr;
|
||||
GeometryTileSource::Callback callback;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -13,12 +13,11 @@
|
||||
namespace mbgl {
|
||||
|
||||
GeometryTileData::GeometryTileData(const OverscaledTileID& id_,
|
||||
std::unique_ptr<GeometryTileSource> tileSource_,
|
||||
std::string sourceID,
|
||||
style::Style& style_,
|
||||
const MapMode mode_,
|
||||
const std::function<void(std::exception_ptr)>& callback)
|
||||
: TileData(id_, std::move(tileSource_)),
|
||||
const std::function<void(std::exception_ptr)>& callback_)
|
||||
: TileData(id_),
|
||||
style(style_),
|
||||
worker(style_.workers),
|
||||
tileWorker(id_,
|
||||
@@ -27,69 +26,68 @@ GeometryTileData::GeometryTileData(const OverscaledTileID& id_,
|
||||
*style_.glyphAtlas,
|
||||
*style_.glyphStore,
|
||||
obsolete,
|
||||
mode_) {
|
||||
auto geometryTileSource = reinterpret_cast<GeometryTileSource*>(tileSource.get());
|
||||
tileRequest = geometryTileSource->monitorTile([callback, this](std::exception_ptr err,
|
||||
std::unique_ptr<GeometryTile> tile,
|
||||
optional<Timestamp> modified_,
|
||||
optional<Timestamp> expires_) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
mode_),
|
||||
callback(callback_) {
|
||||
}
|
||||
|
||||
modified = modified_;
|
||||
expires = expires_;
|
||||
void GeometryTileData::setData(std::exception_ptr err,
|
||||
std::unique_ptr<GeometryTile> tile,
|
||||
optional<Timestamp> modified_,
|
||||
optional<Timestamp> expires_) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!tile) {
|
||||
// This is a 404 response. We're treating these as empty tiles.
|
||||
workRequest.reset();
|
||||
availableData = DataAvailability::All;
|
||||
buckets.clear();
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
modified = modified_;
|
||||
expires = expires_;
|
||||
|
||||
// Mark the tile as pending again if it was complete before to prevent signaling a complete
|
||||
// state despite pending parse operations.
|
||||
if (availableData == DataAvailability::All) {
|
||||
availableData = DataAvailability::Some;
|
||||
}
|
||||
|
||||
// Kick off a fresh parse of this tile. This happens when the tile is new, or
|
||||
// when tile data changed. Replacing the workdRequest will cancel a pending work
|
||||
// request in case there is one.
|
||||
if (!tile) {
|
||||
// This is a 404 response. We're treating these as empty tiles.
|
||||
workRequest.reset();
|
||||
workRequest = worker.parseGeometryTile(tileWorker, style.getLayers(), std::move(tile), targetConfig, [callback, this, config = targetConfig] (TileParseResult result) {
|
||||
workRequest.reset();
|
||||
availableData = DataAvailability::All;
|
||||
buckets.clear();
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
std::exception_ptr error;
|
||||
if (result.is<TileParseResultData>()) {
|
||||
auto& resultBuckets = result.get<TileParseResultData>();
|
||||
availableData =
|
||||
resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
|
||||
// Mark the tile as pending again if it was complete before to prevent signaling a complete
|
||||
// state despite pending parse operations.
|
||||
if (availableData == DataAvailability::All) {
|
||||
availableData = DataAvailability::Some;
|
||||
}
|
||||
|
||||
// Persist the configuration we just placed so that we can later check whether we need to
|
||||
// place again in case the configuration has changed.
|
||||
placedConfig = config;
|
||||
// Kick off a fresh parse of this tile. This happens when the tile is new, or
|
||||
// when tile data changed. Replacing the workdRequest will cancel a pending work
|
||||
// request in case there is one.
|
||||
workRequest.reset();
|
||||
workRequest = worker.parseGeometryTile(tileWorker, style.getLayers(), std::move(tile), targetConfig, [this, config = targetConfig] (TileParseResult result) {
|
||||
workRequest.reset();
|
||||
|
||||
// Move over all buckets we received in this parse request, potentially overwriting
|
||||
// existing buckets in case we got a refresh parse.
|
||||
buckets = std::move(resultBuckets.buckets);
|
||||
std::exception_ptr error;
|
||||
if (result.is<TileParseResultData>()) {
|
||||
auto& resultBuckets = result.get<TileParseResultData>();
|
||||
availableData = resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
|
||||
|
||||
if (isComplete()) {
|
||||
featureIndex = std::move(resultBuckets.featureIndex);
|
||||
geometryTile = std::move(resultBuckets.geometryTile);
|
||||
}
|
||||
// Persist the configuration we just placed so that we can later check whether we need to
|
||||
// place again in case the configuration has changed.
|
||||
placedConfig = config;
|
||||
|
||||
} else {
|
||||
// This is triggered when parsing fails (e.g. due to an invalid vector tile)
|
||||
error = result.get<std::exception_ptr>();
|
||||
availableData = DataAvailability::All;
|
||||
// Move over all buckets we received in this parse request, potentially overwriting
|
||||
// existing buckets in case we got a refresh parse.
|
||||
buckets = std::move(resultBuckets.buckets);
|
||||
|
||||
if (isComplete()) {
|
||||
featureIndex = std::move(resultBuckets.featureIndex);
|
||||
geometryTile = std::move(resultBuckets.geometryTile);
|
||||
}
|
||||
|
||||
callback(error);
|
||||
});
|
||||
} else {
|
||||
error = result.get<std::exception_ptr>();
|
||||
availableData = DataAvailability::All;
|
||||
}
|
||||
|
||||
callback(error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -97,21 +95,20 @@ GeometryTileData::~GeometryTileData() {
|
||||
cancel();
|
||||
}
|
||||
|
||||
bool GeometryTileData::parsePending(std::function<void(std::exception_ptr)> callback) {
|
||||
bool GeometryTileData::parsePending() {
|
||||
if (workRequest) {
|
||||
// There's already parsing or placement going on.
|
||||
return false;
|
||||
}
|
||||
|
||||
workRequest.reset();
|
||||
workRequest = worker.parsePendingGeometryTileLayers(tileWorker, targetConfig, [this, callback, config = targetConfig] (TileParseResult result) {
|
||||
workRequest = worker.parsePendingGeometryTileLayers(tileWorker, targetConfig, [this, config = targetConfig] (TileParseResult result) {
|
||||
workRequest.reset();
|
||||
|
||||
std::exception_ptr error;
|
||||
if (result.is<TileParseResultData>()) {
|
||||
auto& resultBuckets = result.get<TileParseResultData>();
|
||||
availableData =
|
||||
resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
|
||||
availableData = resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
|
||||
|
||||
// Move over all buckets we received in this parse request, potentially overwriting
|
||||
// existing buckets in case we got a refresh parse.
|
||||
@@ -149,20 +146,20 @@ Bucket* GeometryTileData::getBucket(const style::Layer& layer) {
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
void GeometryTileData::redoPlacement(const PlacementConfig newConfig, const std::function<void()>& callback) {
|
||||
void GeometryTileData::redoPlacement(const PlacementConfig newConfig, const std::function<void()>& cb) {
|
||||
if (newConfig != placedConfig) {
|
||||
targetConfig = newConfig;
|
||||
|
||||
redoPlacement(callback);
|
||||
redoPlacement(cb);
|
||||
}
|
||||
}
|
||||
|
||||
void GeometryTileData::redoPlacement(const std::function<void()>& callback) {
|
||||
void GeometryTileData::redoPlacement(const std::function<void()>& cb) {
|
||||
// Don't start a new placement request when the current one hasn't completed yet, or when
|
||||
// we are parsing buckets.
|
||||
if (workRequest) return;
|
||||
|
||||
workRequest = worker.redoPlacement(tileWorker, buckets, targetConfig, [this, callback, config = targetConfig](std::unique_ptr<CollisionTile> collisionTile) {
|
||||
workRequest = worker.redoPlacement(tileWorker, buckets, targetConfig, [this, cb, config = targetConfig](std::unique_ptr<CollisionTile> collisionTile) {
|
||||
workRequest.reset();
|
||||
|
||||
// Persist the configuration we just placed so that we can later check whether we need to
|
||||
@@ -180,9 +177,9 @@ void GeometryTileData::redoPlacement(const std::function<void()>& callback) {
|
||||
// The target configuration could have changed since we started placement. In this case,
|
||||
// we're starting another placement run.
|
||||
if (placedConfig != targetConfig) {
|
||||
redoPlacement(callback);
|
||||
redoPlacement(cb);
|
||||
} else {
|
||||
callback();
|
||||
cb();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -208,7 +205,6 @@ void GeometryTileData::queryRenderedFeatures(
|
||||
|
||||
void GeometryTileData::cancel() {
|
||||
obsolete = true;
|
||||
tileRequest.reset();
|
||||
workRequest.reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
namespace mbgl {
|
||||
|
||||
class AsyncRequest;
|
||||
class GeometryTile;
|
||||
class GeometryTileSource;
|
||||
class FeatureIndex;
|
||||
|
||||
@@ -22,17 +23,21 @@ class Style;
|
||||
class GeometryTileData : public TileData {
|
||||
public:
|
||||
GeometryTileData(const OverscaledTileID&,
|
||||
std::unique_ptr<GeometryTileSource> tileSource,
|
||||
std::string sourceID,
|
||||
style::Style&,
|
||||
const MapMode,
|
||||
const std::function<void(std::exception_ptr)>& callback);
|
||||
std::string sourceID,
|
||||
style::Style&,
|
||||
const MapMode,
|
||||
const std::function<void(std::exception_ptr)>& callback);
|
||||
|
||||
~GeometryTileData();
|
||||
|
||||
void setData(std::exception_ptr err,
|
||||
std::unique_ptr<GeometryTile> tile,
|
||||
optional<Timestamp> modified_,
|
||||
optional<Timestamp> expires_);
|
||||
|
||||
Bucket* getBucket(const style::Layer&) override;
|
||||
|
||||
bool parsePending(std::function<void(std::exception_ptr)> callback) override;
|
||||
bool parsePending() override;
|
||||
|
||||
void redoPlacement(PlacementConfig config, const std::function<void()>&) override;
|
||||
void redoPlacement(const std::function<void()>&) override;
|
||||
@@ -50,7 +55,6 @@ private:
|
||||
Worker& worker;
|
||||
TileWorker tileWorker;
|
||||
|
||||
std::unique_ptr<AsyncRequest> tileRequest;
|
||||
std::unique_ptr<AsyncRequest> workRequest;
|
||||
|
||||
// Contains all the Bucket objects for the tile. Buckets are render
|
||||
@@ -69,6 +73,8 @@ private:
|
||||
|
||||
// Used to signal the worker that it should abandon parsing this tile as soon as possible.
|
||||
util::Atomic<bool> obsolete { false };
|
||||
|
||||
const std::function<void(std::exception_ptr)> callback;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
25
src/mbgl/tile/image_tile_source.cpp
Normal file
25
src/mbgl/tile/image_tile_source.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <mbgl/tile/image_tile_source.hpp>
|
||||
#include <mbgl/tile/raster_tile_data.hpp>
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
ImageTileSource::ImageTileSource(RasterTileData& tileData_,
|
||||
const Resource& resource_,
|
||||
FileSource& fileSource_)
|
||||
: RasterTileSource(tileData_), resource(resource_), fileSource(fileSource_) {
|
||||
request = fileSource.request(resource, [this](Response res) {
|
||||
if (res.error) {
|
||||
tileData.setData(std::make_exception_ptr(std::runtime_error(res.error->message)),
|
||||
nullptr, res.modified, res.expires);
|
||||
} else if (res.notModified) {
|
||||
return;
|
||||
} else if (res.noContent) {
|
||||
tileData.setData(nullptr, nullptr, res.modified, res.expires);
|
||||
} else {
|
||||
tileData.setData(nullptr, res.data, res.modified, res.expires);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
23
src/mbgl/tile/image_tile_source.hpp
Normal file
23
src/mbgl/tile/image_tile_source.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/tile/tile_source.hpp>
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class FileSource;
|
||||
class AsyncRequest;
|
||||
|
||||
class ImageTileSource : public RasterTileSource {
|
||||
public:
|
||||
ImageTileSource(RasterTileData&, const Resource&, FileSource&);
|
||||
virtual ~ImageTileSource() = default;
|
||||
|
||||
private:
|
||||
const Resource resource;
|
||||
FileSource& fileSource;
|
||||
std::unique_ptr<AsyncRequest> request;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,6 +1,5 @@
|
||||
#include <mbgl/tile/raster_tile_data.hpp>
|
||||
#include <mbgl/style/source.hpp>
|
||||
#include <mbgl/tile/raster_tile_source.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
@@ -10,51 +9,51 @@
|
||||
using namespace mbgl;
|
||||
|
||||
RasterTileData::RasterTileData(const OverscaledTileID& id_,
|
||||
std::unique_ptr<RasterTileSource> tileSource_,
|
||||
gl::TexturePool& texturePool_,
|
||||
Worker& worker_,
|
||||
const std::function<void(std::exception_ptr)>& callback)
|
||||
: TileData(id_, std::move(tileSource_)),
|
||||
const std::function<void(std::exception_ptr)>& callback_)
|
||||
: TileData(id_),
|
||||
texturePool(texturePool_),
|
||||
worker(worker_) {
|
||||
auto rasterTileSource = reinterpret_cast<RasterTileSource*>(tileSource.get());
|
||||
tileRequest = rasterTileSource->monitorTile([callback, this](std::exception_ptr err,
|
||||
std::shared_ptr<const std::string> data,
|
||||
optional<Timestamp> modified_,
|
||||
optional<Timestamp> expires_) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
worker(worker_),
|
||||
callback(callback_) {
|
||||
}
|
||||
|
||||
modified = modified_;
|
||||
expires = expires_;
|
||||
void RasterTileData::setData(std::exception_ptr err,
|
||||
std::shared_ptr<const std::string> data,
|
||||
optional<Timestamp> modified_,
|
||||
optional<Timestamp> expires_) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
// This is a 404 response. We're treating these as empty tiles.
|
||||
workRequest.reset();
|
||||
availableData = DataAvailability::All;
|
||||
bucket.reset();
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
modified = modified_;
|
||||
expires = expires_;
|
||||
|
||||
if (!data) {
|
||||
// This is a 404 response. We're treating these as empty tiles.
|
||||
workRequest.reset();
|
||||
workRequest = worker.parseRasterTile(std::make_unique<RasterBucket>(texturePool), data, [this, callback] (RasterTileParseResult result) {
|
||||
workRequest.reset();
|
||||
availableData = DataAvailability::All;
|
||||
bucket.reset();
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
|
||||
std::exception_ptr error;
|
||||
if (result.is<std::unique_ptr<Bucket>>()) {
|
||||
bucket = std::move(result.get<std::unique_ptr<Bucket>>());
|
||||
} else {
|
||||
error = result.get<std::exception_ptr>();
|
||||
bucket.reset();
|
||||
}
|
||||
workRequest.reset();
|
||||
workRequest = worker.parseRasterTile(std::make_unique<RasterBucket>(texturePool), data, [this] (RasterTileParseResult result) {
|
||||
workRequest.reset();
|
||||
|
||||
availableData = DataAvailability::All;
|
||||
std::exception_ptr error;
|
||||
if (result.is<std::unique_ptr<Bucket>>()) {
|
||||
bucket = std::move(result.get<std::unique_ptr<Bucket>>());
|
||||
} else {
|
||||
error = result.get<std::exception_ptr>();
|
||||
bucket.reset();
|
||||
}
|
||||
|
||||
callback(error);
|
||||
});
|
||||
availableData = DataAvailability::All;
|
||||
|
||||
callback(error);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -67,6 +66,5 @@ Bucket* RasterTileData::getBucket(const style::Layer&) {
|
||||
}
|
||||
|
||||
void RasterTileData::cancel() {
|
||||
tileRequest.reset();
|
||||
workRequest.reset();
|
||||
}
|
||||
|
||||
@@ -17,12 +17,16 @@ class Layer;
|
||||
class RasterTileData : public TileData {
|
||||
public:
|
||||
RasterTileData(const OverscaledTileID&,
|
||||
std::unique_ptr<RasterTileSource>,
|
||||
gl::TexturePool&,
|
||||
Worker&,
|
||||
const std::function<void(std::exception_ptr)>& callback);
|
||||
~RasterTileData();
|
||||
|
||||
void setData(std::exception_ptr err,
|
||||
std::shared_ptr<const std::string> data,
|
||||
optional<Timestamp> modified_,
|
||||
optional<Timestamp> expires_);
|
||||
|
||||
void cancel() override;
|
||||
Bucket* getBucket(const style::Layer&) override;
|
||||
|
||||
@@ -30,12 +34,13 @@ private:
|
||||
gl::TexturePool& texturePool;
|
||||
Worker& worker;
|
||||
|
||||
std::unique_ptr<AsyncRequest> tileRequest;
|
||||
std::unique_ptr<AsyncRequest> workRequest;
|
||||
|
||||
// Contains the Bucket object for the tile. Buckets are render
|
||||
// objects and they get added by tile parsing operations.
|
||||
std::unique_ptr<Bucket> bucket;
|
||||
|
||||
const std::function<void(std::exception_ptr)> callback;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#include <mbgl/tile/raster_tile_source.hpp>
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
RasterTileSource::RasterTileSource(const Resource& resource_, FileSource& fileSource_)
|
||||
: resource(resource_), fileSource(fileSource_) {
|
||||
}
|
||||
|
||||
std::unique_ptr<AsyncRequest> RasterTileSource::monitorTile(const Callback& callback) {
|
||||
return fileSource.request(resource, [callback, this](Response res) {
|
||||
if (res.error) {
|
||||
callback(std::make_exception_ptr(std::runtime_error(res.error->message)), nullptr,
|
||||
res.modified, res.expires);
|
||||
} else if (res.notModified) {
|
||||
return;
|
||||
} else if (res.noContent) {
|
||||
callback(nullptr, nullptr, res.modified, res.expires);
|
||||
} else {
|
||||
callback(nullptr, res.data, res.modified, res.expires);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/tile/tile_source.hpp>
|
||||
#include <mbgl/tile/tile_id.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class FileSource;
|
||||
|
||||
class RasterTileSource : public TileSource {
|
||||
public:
|
||||
RasterTileSource(const Resource&, FileSource&);
|
||||
virtual ~RasterTileSource() = default;
|
||||
|
||||
using Callback = std::function<void(std::exception_ptr,
|
||||
std::shared_ptr<const std::string>,
|
||||
optional<Timestamp> modified,
|
||||
optional<Timestamp> expires)>;
|
||||
|
||||
/*
|
||||
* Monitor the tile held by this object for changes. When the tile is loaded for the first time,
|
||||
* or updates, the callback is executed. If an error occurs, the first parameter will be set.
|
||||
* Otherwise it will be null. If there is no data for the requested tile, the second parameter
|
||||
* will be null.
|
||||
*
|
||||
* To cease monitoring, release the returned Request.
|
||||
*/
|
||||
std::unique_ptr<AsyncRequest> monitorTile(const Callback&);
|
||||
|
||||
private:
|
||||
const Resource resource;
|
||||
FileSource& fileSource;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -5,12 +5,18 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
TileData::TileData(const OverscaledTileID& id_, std::unique_ptr<TileSource> tileSource_)
|
||||
: id(id_), tileSource(std::move(tileSource_)) {
|
||||
TileData::TileData(const OverscaledTileID& id_)
|
||||
: id(id_) {
|
||||
}
|
||||
|
||||
TileData::~TileData() = default;
|
||||
|
||||
void TileData::setTileSource(std::unique_ptr<TileSource> tileSource_) {
|
||||
assert(!tileSource);
|
||||
assert(tileSource_);
|
||||
tileSource = std::move(tileSource_);
|
||||
}
|
||||
|
||||
void TileData::dumpDebugLogs() const {
|
||||
Log::Info(Event::General, "TileData::id: %s", util::toString(id).c_str());
|
||||
Log::Info(Event::General, "TileData::renderable: %s", isRenderable() ? "yes" : "no");
|
||||
|
||||
@@ -27,15 +27,17 @@ class Layer;
|
||||
|
||||
class TileData : private util::noncopyable {
|
||||
public:
|
||||
TileData(const OverscaledTileID&, std::unique_ptr<TileSource>);
|
||||
TileData(const OverscaledTileID&);
|
||||
virtual ~TileData();
|
||||
|
||||
void setTileSource(std::unique_ptr<TileSource>);
|
||||
|
||||
// Mark this tile as no longer needed and cancel any pending work.
|
||||
virtual void cancel() = 0;
|
||||
|
||||
virtual Bucket* getBucket(const style::Layer&) = 0;
|
||||
|
||||
virtual bool parsePending(std::function<void (std::exception_ptr)>) { return true; }
|
||||
virtual bool parsePending() { return true; }
|
||||
virtual void redoPlacement(PlacementConfig, const std::function<void()>&) {}
|
||||
virtual void redoPlacement(const std::function<void()>&) {}
|
||||
|
||||
@@ -59,12 +61,12 @@ public:
|
||||
return availableData == DataAvailability::Some;
|
||||
}
|
||||
|
||||
|
||||
void dumpDebugLogs() const;
|
||||
|
||||
const OverscaledTileID id;
|
||||
optional<Timestamp> modified;
|
||||
optional<Timestamp> expires;
|
||||
const std::unique_ptr<TileSource> tileSource;
|
||||
|
||||
// Contains the tile ID string for painting debug information.
|
||||
std::unique_ptr<DebugBucket> debugBucket;
|
||||
@@ -84,6 +86,8 @@ protected:
|
||||
};
|
||||
|
||||
DataAvailability availableData = DataAvailability::None;
|
||||
|
||||
std::unique_ptr<TileSource> tileSource;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#include <mbgl/tile/tile_source.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,39 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/util/optional.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class GeometryTile;
|
||||
class AsyncRequest;
|
||||
|
||||
class TileSource : private util::noncopyable {
|
||||
public:
|
||||
virtual ~TileSource() = default;
|
||||
};
|
||||
|
||||
class GeometryTileData;
|
||||
class RasterTileData;
|
||||
|
||||
class GeometryTileSource : public TileSource {
|
||||
protected:
|
||||
GeometryTileSource(GeometryTileData& tileData_) : tileData(tileData_) {}
|
||||
|
||||
public:
|
||||
virtual ~GeometryTileSource() = default;
|
||||
|
||||
using Callback = std::function<void (std::exception_ptr,
|
||||
std::unique_ptr<GeometryTile>,
|
||||
optional<Timestamp> modified,
|
||||
optional<Timestamp> expires)>;
|
||||
/*
|
||||
* Monitor the tile held by this object for changes. When the tile is loaded for the first time,
|
||||
* or updates, the callback is executed. If an error occurs, the first parameter will be set.
|
||||
* Otherwise it will be null. If there is no data for the requested tile, the second parameter
|
||||
* will be null.
|
||||
*
|
||||
* To cease monitoring, release the returned Request.
|
||||
*/
|
||||
virtual std::unique_ptr<AsyncRequest> monitorTile(const Callback&) = 0;
|
||||
protected:
|
||||
GeometryTileData& tileData;
|
||||
};
|
||||
|
||||
class RasterTileSource : public TileSource {
|
||||
protected:
|
||||
RasterTileSource(RasterTileData& tileData_) : tileData(tileData_) {};
|
||||
|
||||
public:
|
||||
virtual ~RasterTileSource() = default;
|
||||
|
||||
protected:
|
||||
RasterTileData& tileData;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
#include <mbgl/tile/vector_tile_source.hpp>
|
||||
#include <mbgl/tile/vector_tile.hpp>
|
||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
VectorTileSource::VectorTileSource(const Resource& resource_, FileSource& fileSource_)
|
||||
: resource(resource_), fileSource(fileSource_) {
|
||||
}
|
||||
|
||||
std::unique_ptr<AsyncRequest> VectorTileSource::monitorTile(const Callback& callback) {
|
||||
return fileSource.request(resource, [callback, this](Response res) {
|
||||
VectorTileSource::VectorTileSource(GeometryTileData& tileData_,
|
||||
const Resource& resource_,
|
||||
FileSource& fileSource_)
|
||||
: GeometryTileSource(tileData_), resource(resource_), fileSource(fileSource_) {
|
||||
request = fileSource.request(resource, [this](Response res) {
|
||||
if (res.error) {
|
||||
callback(std::make_exception_ptr(std::runtime_error(res.error->message)), nullptr,
|
||||
res.modified, res.expires);
|
||||
tileData.setData(std::make_exception_ptr(std::runtime_error(res.error->message)),
|
||||
nullptr, res.modified, res.expires);
|
||||
} else if (res.notModified) {
|
||||
return;
|
||||
} else if (res.noContent) {
|
||||
callback(nullptr, nullptr, res.modified, res.expires);
|
||||
tileData.setData(nullptr, nullptr, res.modified, res.expires);
|
||||
} else {
|
||||
callback(nullptr, std::make_unique<VectorTile>(res.data), res.modified, res.expires);
|
||||
tileData.setData(nullptr, std::make_unique<VectorTile>(res.data), res.modified,
|
||||
res.expires);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,17 +7,17 @@
|
||||
namespace mbgl {
|
||||
|
||||
class FileSource;
|
||||
class AsyncRequest;
|
||||
|
||||
class VectorTileSource : public GeometryTileSource {
|
||||
public:
|
||||
VectorTileSource(const Resource&, FileSource&);
|
||||
VectorTileSource(GeometryTileData&, const Resource&, FileSource&);
|
||||
virtual ~VectorTileSource() = default;
|
||||
|
||||
std::unique_ptr<AsyncRequest> monitorTile(const Callback&) override;
|
||||
|
||||
private:
|
||||
const Resource resource;
|
||||
FileSource& fileSource;
|
||||
std::unique_ptr<AsyncRequest> request;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
Reference in New Issue
Block a user