[core] introduce a RasterTileMonitor

This commit is contained in:
Konstantin Käfer
2016-05-19 16:50:41 +02:00
parent e8d8f52d2e
commit 99b1df4e46
10 changed files with 145 additions and 62 deletions

View File

@@ -25,6 +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/vector_tile_data.hpp>
#include <mbgl/tile/raster_tile_data.hpp>
@@ -202,9 +203,11 @@ std::unique_ptr<TileData> Source::createTile(const OverscaledTileID& overscaledT
// If we don't find working tile data, we're just going to load it.
if (type == SourceType::Raster) {
data = std::make_unique<RasterTileData>(overscaledTileID, parameters.pixelRatio,
tileset->tiles.at(0), parameters.texturePool,
parameters.worker, parameters.fileSource, callback);
std::unique_ptr<RasterTileSource> monitor;
monitor = std::make_unique<RasterTileSource>(overscaledTileID, parameters.pixelRatio, tileset->tiles.at(0), parameters.fileSource);
data = std::make_unique<RasterTileData>(overscaledTileID, std::move(monitor),
parameters.texturePool, parameters.worker, callback);
} else {
std::unique_ptr<GeometryTileSource> monitor;

View File

@@ -1,5 +1,6 @@
#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>
@@ -9,51 +10,51 @@
using namespace mbgl;
RasterTileData::RasterTileData(const OverscaledTileID& id_,
float pixelRatio,
const std::string& urlTemplate,
gl::TexturePool &texturePool_,
std::unique_ptr<RasterTileSource> tileSource_,
gl::TexturePool& texturePool_,
Worker& worker_,
FileSource& fileSource,
const std::function<void(std::exception_ptr)>& callback)
: TileData(id_),
: TileData(id_, std::move(tileSource_)),
texturePool(texturePool_),
worker(worker_) {
const Resource resource =
Resource::tile(urlTemplate, pixelRatio, id.canonical.x, id.canonical.y, id.canonical.z);
req = fileSource.request(resource, [callback, this](Response res) {
if (res.error) {
callback(std::make_exception_ptr(std::runtime_error(res.error->message)));
} else if (res.notModified) {
modified = res.modified;
expires = res.expires;
} else if (res.noContent) {
availableData = DataAvailability::All;
modified = res.modified;
expires = res.expires;
workRequest.reset();
bucket.reset();
callback(nullptr);
} else {
modified = res.modified;
expires = res.expires;
workRequest.reset();
workRequest = worker.parseRasterTile(std::make_unique<RasterBucket>(texturePool), res.data, [this, callback] (RasterTileParseResult result) {
workRequest.reset();
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();
}
availableData = DataAvailability::All;
callback(error);
});
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;
}
modified = modified_;
expires = expires_;
if (!data) {
// This is a 404 response. We're treating these as empty tiles.
workRequest.reset();
availableData = DataAvailability::All;
bucket.reset();
callback(err);
return;
}
workRequest.reset();
workRequest = worker.parseRasterTile(std::make_unique<RasterBucket>(texturePool), data, [this, callback] (RasterTileParseResult result) {
workRequest.reset();
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();
}
availableData = DataAvailability::All;
callback(error);
});
});
}
@@ -66,6 +67,6 @@ Bucket* RasterTileData::getBucket(const style::Layer&) {
}
void RasterTileData::cancel() {
req = nullptr;
tileRequest.reset();
workRequest.reset();
}

View File

@@ -5,7 +5,7 @@
namespace mbgl {
class FileSource;
class RasterTileSource;
class AsyncRequest;
namespace gl { class TexturePool; }
@@ -17,11 +17,9 @@ class Layer;
class RasterTileData : public TileData {
public:
RasterTileData(const OverscaledTileID&,
float pixelRatio,
const std::string& urlTemplate,
std::unique_ptr<RasterTileSource>,
gl::TexturePool&,
Worker&,
FileSource&,
const std::function<void(std::exception_ptr)>& callback);
~RasterTileData();
@@ -31,9 +29,13 @@ public:
private:
gl::TexturePool& texturePool;
Worker& worker;
std::unique_ptr<AsyncRequest> req;
std::unique_ptr<Bucket> bucket;
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;
};
} // namespace mbgl

View File

@@ -0,0 +1,31 @@
#include <mbgl/tile/raster_tile_source.hpp>
#include <mbgl/storage/file_source.hpp>
namespace mbgl {
RasterTileSource::RasterTileSource(const OverscaledTileID& tileID_,
float pixelRatio_,
const std::string& urlTemplate_,
FileSource& fileSource_)
: tileID(tileID_), pixelRatio(pixelRatio_), urlTemplate(urlTemplate_), fileSource(fileSource_) {
}
std::unique_ptr<AsyncRequest>
RasterTileSource::monitorTile(const Callback& callback) {
const Resource resource = Resource::tile(urlTemplate, pixelRatio, tileID.canonical.x,
tileID.canonical.y, tileID.canonical.z);
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

View File

@@ -0,0 +1,40 @@
#pragma once
#include <mbgl/tile/tile_source.hpp>
#include <mbgl/tile/tile_id.hpp>
namespace mbgl {
class FileSource;
class RasterTileSource : public TileSource {
public:
RasterTileSource(const OverscaledTileID&,
float pixelRatio,
const std::string& urlTemplate,
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:
OverscaledTileID tileID;
float pixelRatio;
std::string urlTemplate;
FileSource& fileSource;
};
} // namespace mbgl

View File

@@ -1,11 +1,12 @@
#include <mbgl/tile/tile_data.hpp>
#include <mbgl/tile/tile_source.hpp>
#include <mbgl/renderer/debug_bucket.hpp>
#include <mbgl/util/string.hpp>
namespace mbgl {
TileData::TileData(const OverscaledTileID& id_)
: id(id_) {
TileData::TileData(const OverscaledTileID& id_, std::unique_ptr<TileSource> tileSource_)
: id(id_), tileSource(std::move(tileSource_)) {
}
TileData::~TileData() = default;

View File

@@ -19,6 +19,7 @@ namespace mbgl {
class Worker;
class DebugBucket;
class TransformState;
class TileSource;
namespace style {
class Layer;
@@ -26,7 +27,7 @@ class Layer;
class TileData : private util::noncopyable {
public:
TileData(const OverscaledTileID&);
TileData(const OverscaledTileID&, std::unique_ptr<TileSource>);
virtual ~TileData();
// Mark this tile as no longer needed and cancel any pending work.
@@ -63,6 +64,7 @@ public:
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;

View File

@@ -12,7 +12,12 @@ namespace mbgl {
class GeometryTile;
class AsyncRequest;
class GeometryTileSource : private util::noncopyable {
class TileSource : private util::noncopyable {
public:
virtual ~TileSource() = default;
};
class GeometryTileSource : public TileSource {
public:
virtual ~GeometryTileSource() = default;

View File

@@ -13,12 +13,12 @@
namespace mbgl {
VectorTileData::VectorTileData(const OverscaledTileID& id_,
std::unique_ptr<GeometryTileSource> monitor_,
std::unique_ptr<GeometryTileSource> tileSource_,
std::string sourceID,
style::Style& style_,
const MapMode mode_,
const std::function<void(std::exception_ptr)>& callback)
: TileData(id_),
: TileData(id_, std::move(tileSource_)),
style(style_),
worker(style_.workers),
tileWorker(id_,
@@ -27,10 +27,9 @@ VectorTileData::VectorTileData(const OverscaledTileID& id_,
*style_.glyphAtlas,
*style_.glyphStore,
obsolete,
mode_),
monitor(std::move(monitor_))
{
tileRequest = monitor->monitorTile([callback, this](std::exception_ptr err,
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_) {

View File

@@ -22,7 +22,7 @@ class Style;
class VectorTileData : public TileData {
public:
VectorTileData(const OverscaledTileID&,
std::unique_ptr<GeometryTileSource> monitor,
std::unique_ptr<GeometryTileSource> tileSource,
std::string sourceID,
style::Style&,
const MapMode,
@@ -50,7 +50,6 @@ private:
Worker& worker;
TileWorker tileWorker;
std::unique_ptr<GeometryTileSource> monitor;
std::unique_ptr<AsyncRequest> tileRequest;
std::unique_ptr<AsyncRequest> workRequest;