diff options
65 files changed, 659 insertions, 467 deletions
diff --git a/benchmark/api/query.benchmark.cpp b/benchmark/api/query.benchmark.cpp index 47eba7a9fe..5e273d69ac 100644 --- a/benchmark/api/query.benchmark.cpp +++ b/benchmark/api/query.benchmark.cpp @@ -7,7 +7,6 @@ #include <mbgl/renderer/renderer.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/image.hpp> -#include <mbgl/storage/default_file_source.hpp> #include <mbgl/storage/network_status.hpp> #include <mbgl/util/image.hpp> #include <mbgl/util/io.hpp> @@ -21,7 +20,6 @@ class QueryBenchmark { public: QueryBenchmark() { NetworkStatus::Set(NetworkStatus::Status::Offline); - fileSource.setAccessToken("foobar"); map.getStyle().loadJSON(util::read_file("benchmark/fixtures/api/style.json")); map.jumpTo(CameraOptions().withCenter(LatLng { 40.726989, -73.992857 }).withZoom(15.0)); // Manhattan @@ -32,11 +30,11 @@ public: } util::RunLoop loop; - DefaultFileSource fileSource{ "benchmark/fixtures/api/cache.db", "." }; ThreadPool threadPool{ 4 }; HeadlessFrontend frontend { { 1000, 1000 }, 1, threadPool }; - Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, - fileSource, threadPool, MapOptions().withMapMode(MapMode::Static) }; + Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, threadPool, + MapOptions().withMapMode(MapMode::Static), + ResourceOptions().withCachePath("benchmark/fixtures/api/cache.db").withAssetPath(".").withAccessToken("foobar") }; ScreenBox box{{ 0, 0 }, { 1000, 1000 }}; }; diff --git a/benchmark/api/render.benchmark.cpp b/benchmark/api/render.benchmark.cpp index 9a91e8b3bc..0e7a3be322 100644 --- a/benchmark/api/render.benchmark.cpp +++ b/benchmark/api/render.benchmark.cpp @@ -8,7 +8,7 @@ #include <mbgl/renderer/renderer.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/image.hpp> -#include <mbgl/storage/default_file_source.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/storage/network_status.hpp> #include <mbgl/util/image.hpp> #include <mbgl/util/io.hpp> @@ -22,11 +22,9 @@ class RenderBenchmark { public: RenderBenchmark() { NetworkStatus::Set(NetworkStatus::Status::Offline); - fileSource.setAccessToken("foobar"); } util::RunLoop loop; - DefaultFileSource fileSource { "benchmark/fixtures/api/cache.db", "." }; ThreadPool threadPool { 4 }; }; @@ -42,8 +40,9 @@ static void prepare(Map& map, optional<std::string> json = {}) { static void API_renderStill_reuse_map(::benchmark::State& state) { RenderBenchmark bench; HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.threadPool }; - Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, - bench.fileSource, bench.threadPool, MapOptions().withMapMode(MapMode::Static) }; + Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.threadPool, + MapOptions().withMapMode(MapMode::Static), + ResourceOptions().withCachePath("benchmark/fixtures/api/cache.db").withAssetPath(".").withAccessToken("foobar") }; prepare(map); while (state.KeepRunning()) { @@ -54,8 +53,9 @@ static void API_renderStill_reuse_map(::benchmark::State& state) { static void API_renderStill_reuse_map_formatted_labels(::benchmark::State& state) { RenderBenchmark bench; HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.threadPool }; - Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, - bench.fileSource, bench.threadPool, MapOptions().withMapMode(MapMode::Static) }; + Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.threadPool, + MapOptions().withMapMode(MapMode::Static), + ResourceOptions().withCachePath("benchmark/fixtures/api/cache.db").withAssetPath(".").withAccessToken("foobar") }; prepare(map, util::read_file("benchmark/fixtures/api/style_formatted_labels.json")); while (state.KeepRunning()) { @@ -66,8 +66,9 @@ static void API_renderStill_reuse_map_formatted_labels(::benchmark::State& state static void API_renderStill_reuse_map_switch_styles(::benchmark::State& state) { RenderBenchmark bench; HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.threadPool }; - Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, - bench.fileSource, bench.threadPool, MapOptions().withMapMode(MapMode::Static) }; + Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.threadPool, + MapOptions().withMapMode(MapMode::Static), + ResourceOptions().withCachePath("benchmark/fixtures/api/cache.db").withAssetPath(".").withAccessToken("foobar") }; while (state.KeepRunning()) { prepare(map, { "{}" }); @@ -79,11 +80,11 @@ static void API_renderStill_reuse_map_switch_styles(::benchmark::State& state) { static void API_renderStill_recreate_map(::benchmark::State& state) { RenderBenchmark bench; - + auto mapOptions = MapOptions().withMapMode(MapMode::Static); + auto resourceOptions = ResourceOptions().withCachePath("benchmark/fixtures/api/cache.db").withAssetPath(".").withAccessToken("foobar"); while (state.KeepRunning()) { HeadlessFrontend frontend { { 1000, 1000 }, 1, bench.threadPool }; - Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, - bench.fileSource, bench.threadPool, MapOptions().withMapMode(MapMode::Static) }; + Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), 1, bench.threadPool, mapOptions, resourceOptions }; prepare(map); frontend.render(map); } diff --git a/bin/render.cpp b/bin/render.cpp index 87a1e670b9..41701913b0 100644 --- a/bin/render.cpp +++ b/bin/render.cpp @@ -6,7 +6,6 @@ #include <mbgl/gl/headless_frontend.hpp> #include <mbgl/util/default_thread_pool.hpp> -#include <mbgl/storage/default_file_source.hpp> #include <mbgl/style/style.hpp> #include <args/args.hxx> @@ -76,17 +75,12 @@ int main(int argc, char *argv[]) { using namespace mbgl; util::RunLoop loop; - DefaultFileSource fileSource(cache_file, asset_root); - - // Set access token if present - if (token.size()) { - fileSource.setAccessToken(std::string(token)); - } ThreadPool threadPool(4); HeadlessFrontend frontend({ width, height }, pixelRatio, threadPool); - Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, - fileSource, threadPool, MapOptions().withMapMode(MapMode::Static)); + Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, threadPool, + MapOptions().withMapMode(MapMode::Static), + ResourceOptions().withCachePath(cache_file).withAssetPath(asset_root).withAccessToken(std::string(token))); if (style.find("://") == std::string::npos) { style = std::string("file://") + style; diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index b4f60a19ba..be8bf45142 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -12,6 +12,7 @@ #include <mbgl/map/camera.hpp> #include <mbgl/util/geometry.hpp> #include <mbgl/map/projection_mode.hpp> +#include <mbgl/storage/resource_options.hpp> #include <cstdint> #include <string> @@ -21,7 +22,6 @@ namespace mbgl { -class FileSource; class Scheduler; class RendererFrontend; @@ -36,9 +36,9 @@ public: MapObserver&, Size size, float pixelRatio, - FileSource&, Scheduler&, - const MapOptions&); + const MapOptions&, + const ResourceOptions&); ~Map(); // Register a callback that will get called (on the render thread) when all resources have @@ -137,9 +137,12 @@ public: bool isFullyLoaded() const; void dumpDebugLogs() const; -private: +protected: class Impl; const std::unique_ptr<Impl> impl; + + // For testing only. + Map(std::unique_ptr<Impl>); }; } // namespace mbgl diff --git a/include/mbgl/map/map_options.hpp b/include/mbgl/map/map_options.hpp index 13772332a8..f2297484a3 100644 --- a/include/mbgl/map/map_options.hpp +++ b/include/mbgl/map/map_options.hpp @@ -3,14 +3,13 @@ #include <mbgl/map/mode.hpp> #include <memory> -#include <string> namespace mbgl { /** * @brief Holds values for Map options. */ -class MapOptions { +class MapOptions final { public: /** * @brief Constructs a MapOptions object with default values. @@ -69,52 +68,6 @@ public: ViewportMode viewportMode() const; /** - * @brief Sets the cache path. - * - * @param path Cache path. - * @return reference to MapOptions for chaining options together. - */ - MapOptions& withCachePath(std::string path); - - /** - * @brief Gets the previously set (or default) cache path. - * - * @return cache path - */ - const std::string& cachePath() const; - - /** - * @brief Sets the asset path, which is the root directory from where - * the asset:// scheme gets resolved in a style. - * - * @param path Asset path. - * @return reference to MapOptions for chaining options together. - */ - MapOptions& withAssetRoot(std::string path); - - /** - * @brief Gets the previously set (or default) asset path. - * - * @return asset path - */ - const std::string& assetRoot() const; - - /** - * @brief Sets the maximum cache size. - * - * @param size Cache maximum size in bytes. - * @return reference to MapOptions for chaining options together. - */ - MapOptions& withMaximumCacheSize(uint64_t size); - - /** - * @brief Gets the previously set (or default) maximum allowed cache size. - * - * @return maximum allowed cache database size in bytes. - */ - uint64_t maximumCacheSize() const; - - /** * @brief Specify whether to enable cross-source symbol collision detection * or not. By default, it is set to true. * diff --git a/include/mbgl/storage/default_file_source.hpp b/include/mbgl/storage/default_file_source.hpp index 5f6999e99f..8f88964acf 100644 --- a/include/mbgl/storage/default_file_source.hpp +++ b/include/mbgl/storage/default_file_source.hpp @@ -28,7 +28,7 @@ public: * of megabytes). */ DefaultFileSource(const std::string& cachePath, - const std::string& assetRoot, + const std::string& assetPath, uint64_t maximumCacheSize = util::DEFAULT_MAX_CACHE_SIZE); DefaultFileSource(const std::string& cachePath, std::unique_ptr<FileSource>&& assetFileSource, diff --git a/include/mbgl/storage/file_source.hpp b/include/mbgl/storage/file_source.hpp index 0709a1c245..868dbf7347 100644 --- a/include/mbgl/storage/file_source.hpp +++ b/include/mbgl/storage/file_source.hpp @@ -1,16 +1,21 @@ #pragma once +#include <mbgl/actor/actor_ref.hpp> #include <mbgl/storage/response.hpp> #include <mbgl/storage/resource.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/async_request.hpp> +#include <mbgl/util/optional.hpp> #include <functional> #include <memory> namespace mbgl { +class ResourceOptions; +class ResourceTransform; + class FileSource : private util::noncopyable { public: virtual ~FileSource() = default; @@ -31,6 +36,13 @@ public: virtual bool supportsCacheOnlyRequests() const { return false; } + + // Factory for creating a platform-specific file source. + static std::shared_ptr<FileSource> createPlatformFileSource(const ResourceOptions&); + + // Singleton for obtaining the shared platform-specific file source. A single instance of a file source is provided + // for each unique combination of a Mapbox API base URL, access token, cache path and platform context. + static std::shared_ptr<FileSource> getSharedFileSource(const ResourceOptions&); }; } // namespace mbgl diff --git a/include/mbgl/storage/resource_options.hpp b/include/mbgl/storage/resource_options.hpp new file mode 100644 index 0000000000..0a4669ea15 --- /dev/null +++ b/include/mbgl/storage/resource_options.hpp @@ -0,0 +1,116 @@ +#pragma once + +#include <memory> +#include <string> + +namespace mbgl { + +/** + * @brief Holds values for resource options. + */ +class ResourceOptions final { +public: + /** + * @brief Constructs a ResourceOptions object with default values. + */ + ResourceOptions(); + ~ResourceOptions(); + + /** + * @brief Sets the Mapbox access token - see https://docs.mapbox.com/help/how-mapbox-works/access-tokens/ for details. + * + * @param token Mapbox access token. + * @return reference to ResourceOptions for chaining options together. + */ + ResourceOptions& withAccessToken(std::string token); + + /** + * @brief Gets the previously set (or default) Mapbox access token. + * + * @return const std::string& Mapbox access token. + */ + const std::string& accessToken() const; + + /** + * @brief Sets the API base URL. Default is https://api.mapbox.com for Mapbox. + * + * @param baseURL API base URL. + * @return reference to ResourceOptions for chaining options together. + */ + ResourceOptions& withBaseURL(std::string baseURL); + + /** + * @brief Gets the previously set (or default) API base URL. + * + * @return const std::string& API base URL. + */ + const std::string& baseURL() const; + + /** + * @brief Sets the cache path. + * + * @param path Cache path. + * @return reference to ResourceOptions for chaining options together. + */ + ResourceOptions& withCachePath(std::string path); + + /** + * @brief Gets the previously set (or default) cache path. + * + * @return cache path + */ + const std::string& cachePath() const; + + /** + * @brief Sets the asset path, which is the root directory from where + * the asset:// scheme gets resolved in a style. + * + * @param path Asset path. + * @return reference to ResourceOptions for chaining options together. + */ + ResourceOptions& withAssetPath(std::string path); + + /** + * @brief Gets the previously set (or default) asset path. + * + * @return asset path + */ + const std::string& assetPath() const; + + /** + * @brief Sets the maximum cache size. + * + * @param size Cache maximum size in bytes. + * @return reference to ResourceOptions for chaining options together. + */ + ResourceOptions& withMaximumCacheSize(uint64_t size); + + /** + * @brief Gets the previously set (or default) maximum allowed cache size. + * + * @return maximum allowed cache database size in bytes. + */ + uint64_t maximumCacheSize() const; + + /** + * @brief Sets the platform context. A platform context is usually an object + * that assists the creation of a file source. + * + * @param context Platform context. + * @return reference to ResourceOptions for chaining options together. + */ + ResourceOptions& withPlatformContext(void* context); + + /** + * @brief Gets the previously set (or default) platform context. + * + * @return Platform context. + */ + void* platformContext() const; + +private: + class Impl; + std::shared_ptr<Impl> impl_; +}; + +} // namespace mbgl diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp index 4cfb545b84..bb1f30981b 100644 --- a/platform/android/src/file_source.cpp +++ b/platform/android/src/file_source.cpp @@ -3,6 +3,7 @@ #include <mbgl/actor/actor.hpp> #include <mbgl/actor/scheduler.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/storage/resource_transform.hpp> #include <mbgl/util/logging.hpp> @@ -11,6 +12,14 @@ #include "asset_manager_file_source.hpp" namespace mbgl { + +std::shared_ptr<FileSource> FileSource::createPlatformFileSource(const ResourceOptions& options) { + auto* assetFileSource = reinterpret_cast<AssetManagerFileSource*>(options.platformContext()); + auto fileSource = std::make_shared<DefaultFileSource>(options.cachePath(), std::unique_ptr<AssetManagerFileSource>(assetFileSource)); + fileSource->setAccessToken(options.accessToken()); + return fileSource; +} + namespace android { // FileSource // @@ -22,15 +31,13 @@ FileSource::FileSource(jni::JNIEnv& _env, std::string path = jni::Make<std::string>(_env, _cachePath); mapbox::sqlite::setTempPath(path); - // Create a core default file source - fileSource = std::make_unique<mbgl::DefaultFileSource>( - path + DATABASE_FILE, - std::make_unique<AssetManagerFileSource>(_env, assetManager)); + resourceOptions = mbgl::ResourceOptions() + .withAccessToken(accessToken ? jni::Make<std::string>(_env, accessToken) : "") + .withCachePath(path + DATABASE_FILE) + .withPlatformContext(reinterpret_cast<void*>(new AssetManagerFileSource(_env, assetManager))); - // Set access token - if (accessToken) { - fileSource->setAccessToken(jni::Make<std::string>(_env, accessToken)); - } + // Create a core default file source + fileSource = std::static_pointer_cast<mbgl::DefaultFileSource>(mbgl::FileSource::getSharedFileSource(resourceOptions)); } FileSource::~FileSource() { @@ -110,10 +117,10 @@ FileSource* FileSource::getNativePeer(jni::JNIEnv& env, const jni::Object<FileSo return reinterpret_cast<FileSource *>(jFileSource.Get(env, field)); } -mbgl::DefaultFileSource& FileSource::getDefaultFileSource(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) { +mbgl::ResourceOptions FileSource::getSharedResourceOptions(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) { FileSource* fileSource = FileSource::getNativePeer(env, jFileSource); assert(fileSource != nullptr); - return *fileSource->fileSource; + return fileSource->resourceOptions; } void FileSource::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/file_source.hpp b/platform/android/src/file_source.hpp index 575702120e..3001a5e0f0 100644 --- a/platform/android/src/file_source.hpp +++ b/platform/android/src/file_source.hpp @@ -1,6 +1,7 @@ #pragma once #include <mbgl/storage/default_file_source.hpp> +#include <mbgl/storage/resource_options.hpp> #include "asset_manager.hpp" @@ -49,15 +50,16 @@ public: static FileSource* getNativePeer(jni::JNIEnv&, const jni::Object<FileSource>&); - static mbgl::DefaultFileSource& getDefaultFileSource(jni::JNIEnv&, const jni::Object<FileSource>&); + static mbgl::ResourceOptions getSharedResourceOptions(jni::JNIEnv&, const jni::Object<FileSource>&); static void registerNative(jni::JNIEnv&); private: const std::string DATABASE_FILE = "/mbgl-offline.db"; optional<int> activationCounter; + mbgl::ResourceOptions resourceOptions; std::unique_ptr<Actor<ResourceTransform>> resourceTransform; - std::unique_ptr<mbgl::DefaultFileSource> fileSource; + std::shared_ptr<mbgl::DefaultFileSource> fileSource; }; diff --git a/platform/android/src/map_renderer.hpp b/platform/android/src/map_renderer.hpp index 3e5b99605e..57265cebb1 100644 --- a/platform/android/src/map_renderer.hpp +++ b/platform/android/src/map_renderer.hpp @@ -1,13 +1,15 @@ #pragma once +#include <mbgl/actor/actor_ref.hpp> #include <mbgl/actor/scheduler.hpp> #include <mbgl/util/image.hpp> +#include <mbgl/util/optional.hpp> #include <memory> +#include <mutex> #include <utility> #include <jni/jni.hpp> -#include <mbgl/storage/default_file_source.hpp> namespace mbgl { diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index 3a4e2014ba..1eb4c56728 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -13,6 +13,7 @@ #include <jni/jni.hpp> +#include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/math/minmax.hpp> #include <mbgl/util/constants.hpp> @@ -74,9 +75,6 @@ NativeMapView::NativeMapView(jni::JNIEnv& _env, return; } - // Get native peer for file source - mbgl::FileSource& fileSource = mbgl::android::FileSource::getDefaultFileSource(_env, jFileSource); - // Create a renderer frontend rendererFrontend = std::make_unique<AndroidRendererFrontend>(mapRenderer); @@ -88,10 +86,9 @@ NativeMapView::NativeMapView(jni::JNIEnv& _env, .withCrossSourceCollisions(_crossSourceCollisions); // Create the core map - map = std::make_unique<mbgl::Map>(*rendererFrontend, *this, - mbgl::Size{ static_cast<uint32_t>(width), - static_cast<uint32_t>(height) }, pixelRatio, - fileSource, *threadPool, options); + map = std::make_unique<mbgl::Map>( + *rendererFrontend, *this, mbgl::Size{ static_cast<uint32_t>(width), static_cast<uint32_t>(height) }, + pixelRatio, *threadPool, options, mbgl::android::FileSource::getSharedResourceOptions(_env, jFileSource)); } /** diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index d695a91ce0..903543e5d1 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -6,7 +6,6 @@ #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/default_thread_pool.hpp> #include <mbgl/util/run_loop.hpp> -#include <mbgl/storage/default_file_source.hpp> #include <mbgl/storage/network_status.hpp> #include "annotation/marker.hpp" diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp index 968c33b644..54b1142845 100644 --- a/platform/android/src/offline/offline_manager.cpp +++ b/platform/android/src/offline/offline_manager.cpp @@ -10,20 +10,19 @@ namespace android { // OfflineManager // OfflineManager::OfflineManager(jni::JNIEnv& env, const jni::Object<FileSource>& jFileSource) - : fileSource(mbgl::android::FileSource::getDefaultFileSource(env, jFileSource)) { -} + : fileSource(std::static_pointer_cast<DefaultFileSource>(mbgl::FileSource::getSharedFileSource(FileSource::getSharedResourceOptions(env, jFileSource)))) {} OfflineManager::~OfflineManager() {} void OfflineManager::setOfflineMapboxTileCountLimit(jni::JNIEnv&, jni::jlong limit) { - fileSource.setOfflineMapboxTileCountLimit(limit); + fileSource->setOfflineMapboxTileCountLimit(limit); } void OfflineManager::listOfflineRegions(jni::JNIEnv& env_, const jni::Object<FileSource>& jFileSource_, const jni::Object<ListOfflineRegionsCallback>& callback_) { auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_); - fileSource.listOfflineRegions([ + fileSource->listOfflineRegions([ //Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)), jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource)) @@ -59,7 +58,7 @@ void OfflineManager::createOfflineRegion(jni::JNIEnv& env_, auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_); // Create region - fileSource.createOfflineRegion(definition, metadata, [ + fileSource->createOfflineRegion(definition, metadata, [ //Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)), jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource)) @@ -86,7 +85,7 @@ void OfflineManager::mergeOfflineRegions(jni::JNIEnv& env_, const jni::Object<Fi auto globalFilesource = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, jFileSource_); auto path = jni::Make<std::string>(env_, jString_); - fileSource.mergeOfflineRegions(path, [ + fileSource->mergeOfflineRegions(path, [ //Keep a shared ptr to a global reference of the callback and file source so they are not GC'd in the meanwhile callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)), jFileSource = std::make_shared<decltype(globalFilesource)>(std::move(globalFilesource)) @@ -226,7 +225,7 @@ void OfflineManager::putResourceWithUrl(jni::JNIEnv& env, response.expires = Timestamp(mbgl::Seconds(expires)); } - fileSource.put(resource, response); + fileSource->put(resource, response); } } // namespace android diff --git a/platform/android/src/offline/offline_manager.hpp b/platform/android/src/offline/offline_manager.hpp index f8d57b88da..d0b637b900 100644 --- a/platform/android/src/offline/offline_manager.hpp +++ b/platform/android/src/offline/offline_manager.hpp @@ -1,7 +1,5 @@ #pragma once - -#include <mbgl/storage/default_file_source.hpp> #include <mbgl/storage/offline.hpp> #include <jni/jni.hpp> @@ -10,8 +8,12 @@ #include "offline_region_definition.hpp" #include "../java_types.hpp" +#include <memory> namespace mbgl { + +class DefaultFileSource; + namespace android { class OfflineManager { @@ -85,7 +87,7 @@ public: private: - mbgl::DefaultFileSource& fileSource; + std::shared_ptr<mbgl::DefaultFileSource> fileSource; }; } // namespace android diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp index 1cd73a7c76..e0f28631b4 100644 --- a/platform/android/src/offline/offline_region.cpp +++ b/platform/android/src/offline/offline_region.cpp @@ -14,8 +14,8 @@ namespace android { // OfflineRegion // OfflineRegion::OfflineRegion(jni::JNIEnv& env, jni::jlong offlineRegionPtr, const jni::Object<FileSource>& jFileSource) - : region(reinterpret_cast<mbgl::OfflineRegion *>(offlineRegionPtr)), - fileSource(mbgl::android::FileSource::getDefaultFileSource(env, jFileSource)) {} + : region(reinterpret_cast<mbgl::OfflineRegion *>(offlineRegionPtr)) + , fileSource(std::static_pointer_cast<DefaultFileSource>(mbgl::FileSource::getSharedFileSource(FileSource::getSharedResourceOptions(env, jFileSource)))) {} OfflineRegion::~OfflineRegion() {} @@ -62,7 +62,7 @@ void OfflineRegion::setOfflineRegionObserver(jni::JNIEnv& env_, const jni::Objec }; // Set the observer - fileSource.setOfflineRegionObserver(*region, std::make_unique<Observer>(jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback))); + fileSource->setOfflineRegionObserver(*region, std::make_unique<Observer>(jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback))); } void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState) { @@ -80,13 +80,13 @@ void OfflineRegion::setOfflineRegionDownloadState(jni::JNIEnv&, jni::jint jState return; } - fileSource.setOfflineRegionDownloadState(*region, state); + fileSource->setOfflineRegionDownloadState(*region, state); } void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, const jni::Object<OfflineRegionStatusCallback>& callback_) { auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); - fileSource.getOfflineRegionStatus(*region, [ + fileSource->getOfflineRegionStatus(*region, [ //Ensure the object is not gc'd in the meanwhile callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)) ](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) mutable { @@ -104,7 +104,7 @@ void OfflineRegion::getOfflineRegionStatus(jni::JNIEnv& env_, const jni::Object< void OfflineRegion::deleteOfflineRegion(jni::JNIEnv& env_, const jni::Object<OfflineRegionDeleteCallback>& callback_) { auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); - fileSource.deleteOfflineRegion(std::move(*region), [ + fileSource->deleteOfflineRegion(std::move(*region), [ //Ensure the object is not gc'd in the meanwhile callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)) ](std::exception_ptr error) mutable { @@ -123,7 +123,7 @@ void OfflineRegion::updateOfflineRegionMetadata(jni::JNIEnv& env_, const jni::Ar auto metadata = OfflineRegion::metadata(env_, jMetadata); auto globalCallback = jni::NewGlobal<jni::EnvAttachingDeleter>(env_, callback_); - fileSource.updateOfflineMetadata(region->getID(), metadata, [ + fileSource->updateOfflineMetadata(region->getID(), metadata, [ //Ensure the object is not gc'd in the meanwhile callback = std::make_shared<decltype(globalCallback)>(std::move(globalCallback)) ](mbgl::expected<mbgl::OfflineRegionMetadata, std::exception_ptr> data) mutable { diff --git a/platform/android/src/offline/offline_region.hpp b/platform/android/src/offline/offline_region.hpp index 49fa0c8ff8..4618e1abbd 100644 --- a/platform/android/src/offline/offline_region.hpp +++ b/platform/android/src/offline/offline_region.hpp @@ -74,7 +74,7 @@ public: private: std::unique_ptr<mbgl::OfflineRegion> region; - mbgl::DefaultFileSource& fileSource; + std::shared_ptr<mbgl::DefaultFileSource> fileSource; }; } // namespace android diff --git a/platform/android/src/snapshotter/map_snapshotter.cpp b/platform/android/src/snapshotter/map_snapshotter.cpp index 8eb1d02605..47a2781cb5 100644 --- a/platform/android/src/snapshotter/map_snapshotter.cpp +++ b/platform/android/src/snapshotter/map_snapshotter.cpp @@ -37,7 +37,6 @@ MapSnapshotter::MapSnapshotter(jni::JNIEnv& _env, } jFileSource = FileSource::getNativePeer(_env, _jFileSource); - auto& fileSource = mbgl::android::FileSource::getDefaultFileSource(_env, _jFileSource); auto size = mbgl::Size { static_cast<uint32_t>(width), static_cast<uint32_t>(height) }; optional<mbgl::CameraOptions> cameraOptions; @@ -56,11 +55,10 @@ MapSnapshotter::MapSnapshotter(jni::JNIEnv& _env, } else { style = std::make_pair(false, jni::Make<std::string>(_env, styleURL)); } - + showLogo = _showLogo; // Create the core snapshotter - snapshotter = std::make_unique<mbgl::MapSnapshotter>(&fileSource, - threadPool, + snapshotter = std::make_unique<mbgl::MapSnapshotter>(threadPool, style, size, pixelRatio, @@ -69,8 +67,8 @@ MapSnapshotter::MapSnapshotter(jni::JNIEnv& _env, jni::Make<std::string>(_env, _programCacheDir), _localIdeographFontFamily ? jni::Make<std::string>(_env, _localIdeographFontFamily) : - optional<std::string>{}); - + optional<std::string>{}, + mbgl::android::FileSource::getSharedResourceOptions(_env, _jFileSource)); } MapSnapshotter::~MapSnapshotter() = default; diff --git a/platform/darwin/filesource-files.json b/platform/darwin/filesource-files.json index 3ee96f9b95..b2e6fbc9b4 100644 --- a/platform/darwin/filesource-files.json +++ b/platform/darwin/filesource-files.json @@ -4,6 +4,7 @@ "platform/darwin/src/MGLLoggingConfiguration.m", "platform/darwin/src/MGLNetworkConfiguration.m", "platform/darwin/src/http_file_source.mm", + "platform/default/src/mbgl/storage/file_source.cpp", "platform/default/src/mbgl/storage/sqlite3.cpp" ], "public_headers": {}, diff --git a/platform/darwin/src/MGLMapSnapshotter.mm b/platform/darwin/src/MGLMapSnapshotter.mm index 169808f774..00ec45f7ff 100644 --- a/platform/darwin/src/MGLMapSnapshotter.mm +++ b/platform/darwin/src/MGLMapSnapshotter.mm @@ -3,8 +3,10 @@ #import <mbgl/actor/actor.hpp> #import <mbgl/actor/scheduler.hpp> #import <mbgl/util/geo.hpp> +#import <mbgl/map/map_options.hpp> #import <mbgl/map/map_snapshotter.hpp> #import <mbgl/map/camera.hpp> +#import <mbgl/storage/resource_options.hpp> #import <mbgl/storage/default_file_source.hpp> #import <mbgl/util/default_thread_pool.hpp> #import <mbgl/util/string.hpp> @@ -587,7 +589,9 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; _cancelled = NO; _options = options; + auto mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; + _mbglThreadPool = mbgl::sharedThreadPool(); std::string styleURL = std::string([options.styleURL.absoluteString UTF8String]); @@ -619,9 +623,14 @@ const CGFloat MGLSnapshotterMinimumPixelSize = 64; // App-global configuration MGLRendererConfiguration* config = [MGLRendererConfiguration currentConfiguration]; - + + auto resourceOptions = mbgl::ResourceOptions() + .withCachePath([[MGLOfflineStorage sharedOfflineStorage] mbglCachePath]) + .withAssetPath([NSBundle mainBundle].resourceURL.path.UTF8String); + // Create the snapshotter - _mbglMapSnapshotter = std::make_unique<mbgl::MapSnapshotter>(mbglFileSource.get(), _mbglThreadPool, style, size, pixelRatio, cameraOptions, coordinateBounds, config.cacheDir, config.localFontFamilyName); + _mbglMapSnapshotter = std::make_unique<mbgl::MapSnapshotter>( + _mbglThreadPool, style, size, pixelRatio, cameraOptions, coordinateBounds, config.cacheDir, config.localFontFamilyName, resourceOptions); } @end diff --git a/platform/darwin/src/MGLOfflinePack.mm b/platform/darwin/src/MGLOfflinePack.mm index 913e9c2233..0f2e8180fa 100644 --- a/platform/darwin/src/MGLOfflinePack.mm +++ b/platform/darwin/src/MGLOfflinePack.mm @@ -10,6 +10,7 @@ #import "NSValue+MGLAdditions.h" +#include <mbgl/map/map_options.hpp> #include <mbgl/storage/default_file_source.hpp> const MGLExceptionName MGLInvalidOfflinePackException = @"MGLInvalidOfflinePackException"; @@ -58,6 +59,7 @@ private: @implementation MGLOfflinePack { BOOL _isSuspending; + std::shared_ptr<mbgl::DefaultFileSource> _mbglFileSource; } - (instancetype)init { @@ -74,8 +76,8 @@ private: _mbglOfflineRegion = region; _state = MGLOfflinePackStateUnknown; - auto mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; - mbglFileSource->setOfflineRegionObserver(*_mbglOfflineRegion, std::make_unique<MBGLOfflineRegionObserver>(self)); + _mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; + _mbglFileSource->setOfflineRegionObserver(*_mbglOfflineRegion, std::make_unique<MBGLOfflineRegionObserver>(self)); } return self; } @@ -115,8 +117,7 @@ private: self.state = MGLOfflinePackStateActive; - auto mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; - mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Active); + _mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Active); } - (void)suspend { @@ -128,8 +129,7 @@ private: _isSuspending = YES; } - auto mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; - mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Inactive); + _mbglFileSource->setOfflineRegionDownloadState(*_mbglOfflineRegion, mbgl::OfflineRegionDownloadState::Inactive); } - (void)invalidate { @@ -137,8 +137,7 @@ private: MGLAssert(_state != MGLOfflinePackStateInvalid, @"Cannot invalidate an already invalid offline pack."); self.state = MGLOfflinePackStateInvalid; - auto mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; - mbglFileSource->setOfflineRegionObserver(*self.mbglOfflineRegion, nullptr); + _mbglFileSource->setOfflineRegionObserver(*self.mbglOfflineRegion, nullptr); self.mbglOfflineRegion = nil; } @@ -164,9 +163,8 @@ private: MGLLogInfo(@"Requesting pack progress."); MGLAssertOfflinePackIsValid(); - auto mbglFileSource = [[MGLOfflineStorage sharedOfflineStorage] mbglFileSource]; __weak MGLOfflinePack *weakSelf = self; - mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) { + _mbglFileSource->getOfflineRegionStatus(*_mbglOfflineRegion, [&, weakSelf](mbgl::expected<mbgl::OfflineRegionStatus, std::exception_ptr> status) { if (status) { mbgl::OfflineRegionStatus checkedStatus = *status; dispatch_async(dispatch_get_main_queue(), ^{ diff --git a/platform/darwin/src/MGLOfflinePack_Private.h b/platform/darwin/src/MGLOfflinePack_Private.h index 8a63152dca..ea3fb2da99 100644 --- a/platform/darwin/src/MGLOfflinePack_Private.h +++ b/platform/darwin/src/MGLOfflinePack_Private.h @@ -1,6 +1,6 @@ #import "MGLOfflinePack.h" -#include <mbgl/storage/default_file_source.hpp> +#include <mbgl/storage/offline.hpp> NS_ASSUME_NONNULL_BEGIN diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm index a118916f86..5f3b2c7c20 100644 --- a/platform/darwin/src/MGLOfflineStorage.mm +++ b/platform/darwin/src/MGLOfflineStorage.mm @@ -19,6 +19,8 @@ #include <mbgl/actor/actor.hpp> #include <mbgl/actor/scheduler.hpp> +#include <mbgl/storage/default_file_source.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/storage/resource_transform.hpp> #include <mbgl/util/chrono.hpp> #include <mbgl/util/run_loop.hpp> @@ -44,6 +46,7 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio @property (nonatomic, strong, readwrite) NSMutableArray<MGLOfflinePack *> *packs; @property (nonatomic) std::shared_ptr<mbgl::DefaultFileSource> mbglFileSource; +@property (nonatomic) std::string mbglCachePath; @property (nonatomic, getter=isPaused) BOOL paused; @end @@ -222,7 +225,10 @@ const MGLExceptionName MGLUnsupportedRegionTypeException = @"MGLUnsupportedRegio [[NSFileManager defaultManager] moveItemAtPath:subdirectorylessCacheURL.path toPath:cachePath error:NULL]; } - _mbglFileSource = std::make_shared<mbgl::DefaultFileSource>(cachePath.UTF8String, [NSBundle mainBundle].resourceURL.path.UTF8String); + _mbglCachePath = cachePath.UTF8String; + auto options = mbgl::ResourceOptions().withCachePath(_mbglCachePath) + .withAssetPath([NSBundle mainBundle].resourceURL.path.UTF8String); + _mbglFileSource = std::static_pointer_cast<mbgl::DefaultFileSource>(mbgl::FileSource::getSharedFileSource(options)); // Observe for changes to the API base URL (and find out the current one). [[MGLAccountManager sharedManager] addObserver:self diff --git a/platform/darwin/src/MGLOfflineStorage_Private.h b/platform/darwin/src/MGLOfflineStorage_Private.h index c4618684ba..5ac64ea995 100644 --- a/platform/darwin/src/MGLOfflineStorage_Private.h +++ b/platform/darwin/src/MGLOfflineStorage_Private.h @@ -15,6 +15,11 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic) std::shared_ptr<mbgl::DefaultFileSource> mbglFileSource; +/** + The shared offline cache path. + */ +@property (nonatomic) std::string mbglCachePath; + @end NS_ASSUME_NONNULL_END diff --git a/platform/default/include/mbgl/map/map_snapshotter.hpp b/platform/default/include/mbgl/map/map_snapshotter.hpp index 2deb2b3cda..ccc3ee17f7 100644 --- a/platform/default/include/mbgl/map/map_snapshotter.hpp +++ b/platform/default/include/mbgl/map/map_snapshotter.hpp @@ -18,6 +18,7 @@ struct CameraOptions; class FileSource; class Size; class LatLngBounds; +class ResourceOptions; namespace style { class Style; @@ -25,15 +26,15 @@ class Style; class MapSnapshotter { public: - MapSnapshotter(FileSource* fileSource, - std::shared_ptr<Scheduler> scheduler, + MapSnapshotter(std::shared_ptr<Scheduler> scheduler, const std::pair<bool, std::string> style, const Size&, const float pixelRatio, const optional<CameraOptions> cameraOptions, const optional<LatLngBounds> region, - const optional<std::string> cacheDir = {}, - const optional<std::string> localFontFamily = {}); + const optional<std::string> cacheDir, + const optional<std::string> localFontFamily, + const ResourceOptions&); ~MapSnapshotter(); diff --git a/platform/default/src/mbgl/map/map_snapshotter.cpp b/platform/default/src/mbgl/map/map_snapshotter.cpp index 415ef7befd..cd8482e4ba 100644 --- a/platform/default/src/mbgl/map/map_snapshotter.cpp +++ b/platform/default/src/mbgl/map/map_snapshotter.cpp @@ -5,7 +5,7 @@ #include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/map/transform_state.hpp> -#include <mbgl/storage/file_source.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/style/style.hpp> #include <mbgl/util/event.hpp> #include <mbgl/map/transform.hpp> @@ -14,15 +14,15 @@ namespace mbgl { class MapSnapshotter::Impl { public: - Impl(FileSource*, - std::shared_ptr<Scheduler>, + Impl(std::shared_ptr<Scheduler>, const std::pair<bool, std::string> style, const Size&, const float pixelRatio, const optional<CameraOptions> cameraOptions, const optional<LatLngBounds> region, const optional<std::string> programCacheDir, - const optional<std::string> localFontFamily = {}); + const optional<std::string> localFontFamily, + const ResourceOptions& resourceOptions); void setStyleURL(std::string styleURL); std::string getStyleURL() const; @@ -47,19 +47,18 @@ private: Map map; }; -MapSnapshotter::Impl::Impl(FileSource* fileSource, - std::shared_ptr<Scheduler> scheduler_, - const std::pair<bool, std::string> style, - const Size& size, - const float pixelRatio, - const optional<CameraOptions> cameraOptions, - const optional<LatLngBounds> region, - const optional<std::string> programCacheDir, - const optional<std::string> localFontFamily) - : scheduler(std::move(scheduler_)) - , frontend(size, pixelRatio, *scheduler, programCacheDir, GLContextMode::Unique, localFontFamily) - , map(frontend, MapObserver::nullObserver(), size, pixelRatio, *fileSource, *scheduler, MapOptions().withMapMode(MapMode::Static)) { - +MapSnapshotter::Impl::Impl(std::shared_ptr<Scheduler> scheduler_, + const std::pair<bool, std::string> style, + const Size& size, + const float pixelRatio, + const optional<CameraOptions> cameraOptions, + const optional<LatLngBounds> region, + const optional<std::string> programCacheDir, + const optional<std::string> localFontFamily, + const ResourceOptions& resourceOptions) + : scheduler(std::move(scheduler_)) + , frontend(size, pixelRatio, *scheduler, programCacheDir, GLContextMode::Unique, localFontFamily) + , map(frontend, MapObserver::nullObserver(), size, pixelRatio, *scheduler, MapOptions().withMapMode(MapMode::Static), resourceOptions) { if (style.first) { map.getStyle().loadJSON(style.second); } else{ @@ -164,17 +163,18 @@ LatLngBounds MapSnapshotter::Impl::getRegion() const { return map.latLngBoundsForCamera(getCameraOptions()); } -MapSnapshotter::MapSnapshotter(FileSource* fileSource, - std::shared_ptr<Scheduler> scheduler, +MapSnapshotter::MapSnapshotter(std::shared_ptr<Scheduler> scheduler, const std::pair<bool, std::string> style, const Size& size, const float pixelRatio, const optional<CameraOptions> cameraOptions, const optional<LatLngBounds> region, const optional<std::string> programCacheDir, - const optional<std::string> localFontFamily) - : impl(std::make_unique<util::Thread<MapSnapshotter::Impl>>("Map Snapshotter", fileSource, std::move(scheduler), style, size, pixelRatio, cameraOptions, region, programCacheDir, localFontFamily)) { -} + const optional<std::string> localFontFamily, + const ResourceOptions& resourceOptions) + : impl(std::make_unique<util::Thread<MapSnapshotter::Impl>>( + "Map Snapshotter", std::move(scheduler), style, size, pixelRatio, cameraOptions, + region, programCacheDir, localFontFamily, resourceOptions)) {} MapSnapshotter::~MapSnapshotter() = default; diff --git a/platform/default/src/mbgl/storage/default_file_source.cpp b/platform/default/src/mbgl/storage/default_file_source.cpp index 32eb8b3d58..4d812044cf 100644 --- a/platform/default/src/mbgl/storage/default_file_source.cpp +++ b/platform/default/src/mbgl/storage/default_file_source.cpp @@ -201,9 +201,9 @@ private: }; DefaultFileSource::DefaultFileSource(const std::string& cachePath, - const std::string& assetRoot, + const std::string& assetPath, uint64_t maximumCacheSize) - : DefaultFileSource(cachePath, std::make_unique<AssetFileSource>(assetRoot), maximumCacheSize) { + : DefaultFileSource(cachePath, std::make_unique<AssetFileSource>(assetPath), maximumCacheSize) { } DefaultFileSource::DefaultFileSource(const std::string& cachePath, diff --git a/platform/default/src/mbgl/storage/file_source.cpp b/platform/default/src/mbgl/storage/file_source.cpp new file mode 100644 index 0000000000..a7bbe82f5a --- /dev/null +++ b/platform/default/src/mbgl/storage/file_source.cpp @@ -0,0 +1,15 @@ +#include <mbgl/storage/resource_options.hpp> +#include <mbgl/storage/default_file_source.hpp> + +#include <memory> + +namespace mbgl { + +std::shared_ptr<FileSource> FileSource::createPlatformFileSource(const ResourceOptions& options) { + auto fileSource = std::make_shared<DefaultFileSource>(options.cachePath(), options.assetPath()); + fileSource->setAccessToken(options.accessToken()); + fileSource->setAPIBaseURL(options.baseURL()); + return fileSource; +} + +} // namespace mbgl diff --git a/platform/glfw/main.cpp b/platform/glfw/main.cpp index 38a41cbf18..8288a009f2 100644 --- a/platform/glfw/main.cpp +++ b/platform/glfw/main.cpp @@ -93,23 +93,22 @@ int main(int argc, char *argv[]) { GLFWView backend(fullscreen, benchmark); view = &backend; - mbgl::DefaultFileSource fileSource(cacheDB, "."); - if (!settings.online) { - fileSource.setOnlineStatus(false); - mbgl::Log::Warning(mbgl::Event::Setup, "Application is offline. Press `O` to toggle online status."); - } - // Set access token if present const char *token = getenv("MAPBOX_ACCESS_TOKEN"); if (token == nullptr) { mbgl::Log::Warning(mbgl::Event::Setup, "no access token set. mapbox.com tiles won't work."); - } else { - fileSource.setAccessToken(std::string(token)); + } + + auto resourceOptions = mbgl::ResourceOptions().withCachePath(cacheDB).withAssetPath(".").withAccessToken(std::string(token)); + auto fileSource = std::static_pointer_cast<mbgl::DefaultFileSource>(mbgl::FileSource::getSharedFileSource(resourceOptions)); + if (!settings.online) { + fileSource->setOnlineStatus(false); + mbgl::Log::Warning(mbgl::Event::Setup, "Application is offline. Press `O` to toggle online status."); } mbgl::ThreadPool threadPool(4); GLFWRendererFrontend rendererFrontend { std::make_unique<mbgl::Renderer>(backend, view->getPixelRatio(), threadPool), backend }; - mbgl::Map map(rendererFrontend, backend, view->getSize(), view->getPixelRatio(), fileSource, threadPool, mbgl::MapOptions()); + mbgl::Map map(rendererFrontend, backend, view->getSize(), view->getPixelRatio(), threadPool, mbgl::MapOptions(), resourceOptions); backend.setMap(&map); @@ -124,9 +123,9 @@ int main(int argc, char *argv[]) { .withPitch(settings.pitch)); map.setDebug(mbgl::MapDebugOptions(settings.debug)); - view->setOnlineStatusCallback([&settings, &fileSource]() { + view->setOnlineStatusCallback([&settings, fileSource]() { settings.online = !settings.online; - fileSource.setOnlineStatus(settings.online); + fileSource->setOnlineStatus(settings.online); mbgl::Log::Info(mbgl::Event::Setup, "Application is %s. Press `O` to toggle online status.", settings.online ? "online" : "offline"); }); @@ -144,13 +143,13 @@ int main(int argc, char *argv[]) { mbgl::Log::Info(mbgl::Event::Setup, "Changed style to: %s", newStyle.name); }); - view->setPauseResumeCallback([&fileSource] () { + view->setPauseResumeCallback([fileSource] () { static bool isPaused = false; if (isPaused) { - fileSource.resume(); + fileSource->resume(); } else { - fileSource.pause(); + fileSource->pause(); } isPaused = !isPaused; diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 2065f92f64..94d56dfff9 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -11,7 +11,7 @@ #include <mbgl/util/platform.hpp> #include <mbgl/storage/reachability.h> #include <mbgl/util/default_thread_pool.hpp> -#include <mbgl/storage/default_file_source.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/storage/network_status.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/image.hpp> @@ -477,14 +477,18 @@ public: BOOL enableCrossSourceCollisions = !config.perSourceCollisions; _rendererFrontend = std::make_unique<MGLRenderFrontend>(std::move(renderer), self, *_mbglView); - mbgl::MapOptions mapOptions; - mapOptions.withMapMode(mbgl::MapMode::Continuous) - .withConstrainMode(mbgl::ConstrainMode::None) - .withViewportMode(mbgl::ViewportMode::Default) - .withCrossSourceCollisions(enableCrossSourceCollisions); + auto mapOptions = mbgl::MapOptions() + .withMapMode(mbgl::MapMode::Continuous) + .withConstrainMode(mbgl::ConstrainMode::None) + .withViewportMode(mbgl::ViewportMode::Default) + .withCrossSourceCollisions(enableCrossSourceCollisions); + + auto resourceOptions = mbgl::ResourceOptions() + .withCachePath([[MGLOfflineStorage sharedOfflineStorage] mbglCachePath]) + .withAssetPath([NSBundle mainBundle].resourceURL.path.UTF8String); NSAssert(!_mbglMap, @"_mbglMap should be NULL"); - _mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, self.size, config.scaleFactor, *[[MGLOfflineStorage sharedOfflineStorage] mbglFileSource], *_mbglThreadPool, mapOptions); + _mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, self.size, config.scaleFactor, *_mbglThreadPool, mapOptions, resourceOptions); // start paused if in IB if (_isTargetingInterfaceBuilder || background) { diff --git a/platform/linux/config.cmake b/platform/linux/config.cmake index 6d4715e451..4405e0583f 100644 --- a/platform/linux/config.cmake +++ b/platform/linux/config.cmake @@ -104,13 +104,8 @@ endmacro() macro(mbgl_filesource) - target_sources(mbgl-filesource - # File source - PRIVATE platform/default/src/mbgl/storage/http_file_source.cpp - - # Database - PRIVATE platform/default/src/mbgl/storage/sqlite3.cpp - ) + # Modify platform/linux/filesource-files.json to change the source files for this target. + target_sources_from_file(mbgl-filesource PRIVATE platform/linux/filesource-files.json) # We're not referencing any cURL symbols since we're dynamically loading it. However, we want to # link the library anyway since we're definitely going to load it on startup anyway. diff --git a/platform/linux/filesource-files.json b/platform/linux/filesource-files.json new file mode 100644 index 0000000000..448f5f8613 --- /dev/null +++ b/platform/linux/filesource-files.json @@ -0,0 +1,10 @@ +{ + "//": "This file can be edited manually and is the canonical source.", + "sources": [ + "platform/default/src/mbgl/storage/file_source.cpp", + "platform/default/src/mbgl/storage/http_file_source.cpp", + "platform/default/src/mbgl/storage/sqlite3.cpp" + ], + "public_headers": {}, + "private_headers": {} +} diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 5b2fae90ab..74189c52f4 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -36,8 +36,8 @@ #import <mbgl/renderer/renderer.hpp> #import <mbgl/renderer/renderer_backend.hpp> #import <mbgl/renderer/backend_scope.hpp> -#import <mbgl/storage/default_file_source.hpp> #import <mbgl/storage/network_status.hpp> +#import <mbgl/storage/resource_options.hpp> #import <mbgl/math/wrap.hpp> #import <mbgl/util/constants.hpp> #import <mbgl/util/chrono.hpp> @@ -290,12 +290,17 @@ public: BOOL enableCrossSourceCollisions = !config.perSourceCollisions; _rendererFrontend = std::make_unique<MGLRenderFrontend>(std::move(renderer), self, *_mbglView, true); - mbgl::MapOptions mapOptions; - mapOptions.withMapMode(mbgl::MapMode::Continuous) - .withConstrainMode(mbgl::ConstrainMode::None) - .withViewportMode(mbgl::ViewportMode::Default) - .withCrossSourceCollisions(enableCrossSourceCollisions); - _mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, self.size, config.scaleFactor, *[[MGLOfflineStorage sharedOfflineStorage] mbglFileSource], *_mbglThreadPool, mapOptions); + auto mapOptions = mbgl::MapOptions() + .withMapMode(mbgl::MapMode::Continuous) + .withConstrainMode(mbgl::ConstrainMode::None) + .withViewportMode(mbgl::ViewportMode::Default) + .withCrossSourceCollisions(enableCrossSourceCollisions); + + auto resourceOptions = mbgl::ResourceOptions() + .withCachePath([[MGLOfflineStorage sharedOfflineStorage] mbglCachePath]) + .withAssetPath([NSBundle mainBundle].resourceURL.path.UTF8String); + + _mbglMap = new mbgl::Map(*_rendererFrontend, *_mbglView, self.size, config.scaleFactor, *_mbglThreadPool, mapOptions, resourceOptions); // Install the OpenGL layer. Interface Builder’s synchronous drawing means // we can’t display a map, so don’t even bother to have a map layer. diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp index 0d69e606c1..0b27d378a7 100644 --- a/platform/node/src/node_map.cpp +++ b/platform/node/src/node_map.cpp @@ -20,15 +20,25 @@ #include <mbgl/style/layers/raster_layer.hpp> #include <mbgl/style/layers/symbol_layer.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/image.hpp> #include <mbgl/style/light.hpp> +#include <mbgl/map/map.hpp> #include <mbgl/map/map_observer.hpp> #include <mbgl/util/exception.hpp> #include <mbgl/util/premultiply.hpp> #include <unistd.h> +namespace mbgl { + +std::shared_ptr<FileSource> FileSource::createPlatformFileSource(const ResourceOptions& options) { + return std::make_shared<node_mbgl::NodeFileSource>(reinterpret_cast<node_mbgl::NodeMap*>(options.platformContext())); +} + +} // namespace mbgl + namespace node_mbgl { struct NodeMap::RenderOptions { @@ -621,13 +631,14 @@ void NodeMap::cancel() { }); frontend = std::make_unique<mbgl::HeadlessFrontend>(mbgl::Size{ 256, 256 }, pixelRatio, threadpool); - mbgl::MapOptions options; - options.withMapMode(mode) - .withConstrainMode(mbgl::ConstrainMode::HeightOnly) - .withViewportMode(mbgl::ViewportMode::Default) - .withCrossSourceCollisions(crossSourceCollisions); + auto mapOptions = mbgl::MapOptions() + .withMapMode(mode) + .withCrossSourceCollisions(crossSourceCollisions); + + auto resourceOptions = mbgl::ResourceOptions().withPlatformContext(reinterpret_cast<void*>(this)); + map = std::make_unique<mbgl::Map>(*frontend, mapObserver, frontend->getSize(), pixelRatio, - fileSource, threadpool, options); + threadpool, mapOptions, resourceOptions); // FIXME: Reload the style after recreating the map. We need to find // a better way of canceling an ongoing rendering on the core level @@ -1205,20 +1216,11 @@ NodeMap::NodeMap(v8::Local<v8::Object> options) : true; }()) , mapObserver(NodeMapObserver()) - , fileSource(this) , frontend(std::make_unique<mbgl::HeadlessFrontend>(mbgl::Size { 256, 256 }, pixelRatio, threadpool)) - , map(std::make_unique<mbgl::Map>(*frontend, - mapObserver, - frontend->getSize(), - pixelRatio, - fileSource, - threadpool, - mbgl::MapOptions().withMapMode(mode) - .withConstrainMode(mbgl::ConstrainMode::HeightOnly) - .withViewportMode(mbgl::ViewportMode::Default) - .withCrossSourceCollisions(crossSourceCollisions))), - async(new uv_async_t) { - + , map(std::make_unique<mbgl::Map>(*frontend, mapObserver, frontend->getSize(), pixelRatio, threadpool, + mbgl::MapOptions().withMapMode(mode).withCrossSourceCollisions(crossSourceCollisions), + mbgl::ResourceOptions().withPlatformContext(reinterpret_cast<void*>(this)))) + , async(new uv_async_t) { async->data = this; uv_async_init(uv_default_loop(), async, [](uv_async_t* h) { reinterpret_cast<NodeMap *>(h->data)->renderFinished(); @@ -1232,8 +1234,6 @@ NodeMap::~NodeMap() { if (map) release(); } -NodeFileSource::NodeFileSource(NodeMap* nodeMap_) : nodeMap(nodeMap_) {} - std::unique_ptr<mbgl::AsyncRequest> NodeFileSource::request(const mbgl::Resource& resource, mbgl::FileSource::Callback callback_) { assert(nodeMap); @@ -1248,15 +1248,15 @@ std::unique_ptr<mbgl::AsyncRequest> NodeFileSource::request(const mbgl::Resource Nan::New<v8::External>(&callback_) }; - auto instance = Nan::NewInstance(Nan::New(NodeRequest::constructor), 2, argv).ToLocalChecked(); + auto instance = Nan::NewInstance(Nan::New(node_mbgl::NodeRequest::constructor), 2, argv).ToLocalChecked(); Nan::Set(instance, Nan::New("url").ToLocalChecked(), Nan::New(resource.url).ToLocalChecked()); Nan::Set(instance, Nan::New("kind").ToLocalChecked(), Nan::New<v8::Integer>(resource.kind)); - auto request = Nan::ObjectWrap::Unwrap<NodeRequest>(instance); + auto request = Nan::ObjectWrap::Unwrap<node_mbgl::NodeRequest>(instance); request->Execute(); - return std::make_unique<NodeRequest::NodeAsyncRequest>(request); + return std::make_unique<node_mbgl::NodeRequest::NodeAsyncRequest>(request); } } // namespace node_mbgl diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp index 9e3eb1ad12..65664b34bb 100644 --- a/platform/node/src/node_map.hpp +++ b/platform/node/src/node_map.hpp @@ -15,26 +15,13 @@ #pragma GCC diagnostic pop namespace mbgl { -class Map; class HeadlessFrontend; } // namespace mbgl namespace node_mbgl { -class NodeMapObserver : public mbgl::MapObserver { - void onDidFailLoadingMap(mbgl::MapLoadError, const std::string&) override; -}; - -class NodeMap; - -class NodeFileSource : public mbgl::FileSource { -public: - NodeFileSource(NodeMap*); - - std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback) final; - -private: - NodeMap* nodeMap; +struct NodeMapObserver : public mbgl::MapObserver { + void onDidFailLoadingMap(mbgl::MapLoadError, const std::string&) final; }; class RenderRequest; @@ -94,7 +81,6 @@ public: bool crossSourceCollisions; NodeThreadPool threadpool; NodeMapObserver mapObserver; - NodeFileSource fileSource; std::unique_ptr<mbgl::HeadlessFrontend> frontend; std::unique_ptr<mbgl::Map> map; @@ -108,4 +94,10 @@ public: bool loaded = false; }; +struct NodeFileSource : public mbgl::FileSource { + NodeFileSource(NodeMap* nodeMap_) : nodeMap(nodeMap_) {} + std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback) final; + NodeMap* nodeMap; +}; + } // namespace node_mbgl diff --git a/platform/qt/qt.cmake b/platform/qt/qt.cmake index 14f09007ac..911af25bc4 100644 --- a/platform/qt/qt.cmake +++ b/platform/qt/qt.cmake @@ -50,6 +50,7 @@ set(MBGL_QT_CORE_FILES set(MBGL_QT_FILESOURCE_FILES # File source + PRIVATE platform/default/src/mbgl/storage/file_source.cpp PRIVATE platform/qt/src/http_file_source.cpp PRIVATE platform/qt/src/http_file_source.hpp PRIVATE platform/qt/src/http_request.cpp diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index b05c82a783..1feeecdd7c 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -10,6 +10,7 @@ #include <mbgl/annotation/annotation.hpp> #include <mbgl/map/camera.hpp> #include <mbgl/map/map.hpp> +#include <mbgl/map/map_options.hpp> #include <mbgl/math/log2.hpp> #include <mbgl/math/minmax.hpp> #include <mbgl/style/style.hpp> @@ -33,7 +34,9 @@ #include <mbgl/style/image.hpp> #include <mbgl/renderer/renderer.hpp> #include <mbgl/renderer/backend_scope.hpp> +#include <mbgl/storage/default_file_source.hpp> #include <mbgl/storage/network_status.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/util/color.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/geo.hpp> @@ -91,49 +94,6 @@ namespace { QThreadStorage<std::shared_ptr<mbgl::util::RunLoop>> loop; -std::shared_ptr<mbgl::DefaultFileSource> sharedDefaultFileSource(const QMapboxGLSettings &settings) { - static std::mutex mutex; - static std::unordered_map<std::string, std::weak_ptr<mbgl::DefaultFileSource>> fileSources; - - const std::string cachePath = settings.cacheDatabasePath().toStdString(); - const std::string accessToken = settings.accessToken().toStdString(); - const std::string apiBaseUrl = settings.apiBaseUrl().toStdString(); - - std::lock_guard<std::mutex> lock(mutex); - - // Purge entries no longer in use. - for (auto it = fileSources.begin(); it != fileSources.end();) { - if (it->second.expired()) { - it = fileSources.erase(it); - } else { - ++it; - } - } - - const auto key = cachePath + "|" + accessToken + "|" + apiBaseUrl; - - // Return an existing FileSource if available. - auto sharedFileSource = fileSources.find(key); - if (sharedFileSource != fileSources.end()) { - auto lockedSharedFileSource = sharedFileSource->second.lock(); - if (lockedSharedFileSource) { - return lockedSharedFileSource; - } - } - - // New path, create a new FileSource. - auto newFileSource = std::make_shared<mbgl::DefaultFileSource>( - cachePath, settings.assetPath().toStdString(), settings.cacheDatabaseMaximumSize()); - - // Setup the FileSource - newFileSource->setAccessToken(accessToken); - newFileSource->setAPIBaseURL(apiBaseUrl); - - fileSources[key] = newFileSource; - - return newFileSource; -} - // Conversion helper functions. mbgl::Size sanitizedSize(const QSize& size) { @@ -1745,22 +1705,29 @@ void QMapboxGL::connectionEstablished() \a copyrightsHtml is a string with a HTML snippet. */ +mbgl::MapOptions mapOptionsFromQMapboxGLSettings(const QMapboxGLSettings &settings) { + return mbgl::MapOptions() + .withMapMode(static_cast<mbgl::MapMode>(settings.mapMode())) + .withConstrainMode(static_cast<mbgl::ConstrainMode>(settings.constrainMode())) + .withViewportMode(static_cast<mbgl::ViewportMode>(settings.viewportMode())); +} + +mbgl::ResourceOptions resourceOptionsFromQMapboxGLSettings(const QMapboxGLSettings &settings) { + return mbgl::ResourceOptions() + .withAccessToken(settings.accessToken().toStdString()) + .withAssetPath(settings.assetPath().toStdString()) + .withBaseURL(settings.apiBaseUrl().toStdString()) + .withCachePath(settings.cacheDatabasePath().toStdString()) + .withMaximumCacheSize(settings.cacheDatabaseMaximumSize()); +} + QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settings, const QSize &size, qreal pixelRatio_) : QObject(q) - , m_fileSourceObj(sharedDefaultFileSource(settings)) , m_threadPool(mbgl::sharedThreadPool()) , m_mode(settings.contextMode()) , m_pixelRatio(pixelRatio_) , m_localFontFamily(settings.localFontFamily()) { - if (settings.resourceTransform()) { - m_resourceTransform = std::make_unique<mbgl::Actor<mbgl::ResourceTransform>>(*mbgl::Scheduler::GetCurrent(), - [callback = settings.resourceTransform()] (mbgl::Resource::Kind, const std::string &&url_) -> std::string { - return callback(std::move(url_)); - }); - m_fileSourceObj->setResourceTransform(m_resourceTransform->self()); - } - // Setup MapObserver m_mapObserver = std::make_unique<QMapboxGLMapObserver>(this); @@ -1770,18 +1737,20 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin connect(m_mapObserver.get(), SIGNAL(mapLoadingFailed(QMapboxGL::MapLoadingFailure,QString)), q, SIGNAL(mapLoadingFailed(QMapboxGL::MapLoadingFailure,QString))); connect(m_mapObserver.get(), SIGNAL(copyrightsChanged(QString)), q, SIGNAL(copyrightsChanged(QString))); - mbgl::MapOptions options; - options.withMapMode(static_cast<mbgl::MapMode>(settings.mapMode())) - .withConstrainMode(static_cast<mbgl::ConstrainMode>(settings.constrainMode())) - .withViewportMode(static_cast<mbgl::ViewportMode>(settings.viewportMode())); - - // Setup the Map object - mapObj = std::make_unique<mbgl::Map>( - *this, // RendererFrontend - *m_mapObserver, - sanitizedSize(size), - m_pixelRatio, *m_fileSourceObj, *m_threadPool, - options); + auto resourceOptions = resourceOptionsFromQMapboxGLSettings(settings); + + // Setup the Map object. + mapObj = std::make_unique<mbgl::Map>(*this, *m_mapObserver, sanitizedSize(size), m_pixelRatio, *m_threadPool, + mapOptionsFromQMapboxGLSettings(settings), resourceOptions); + + if (settings.resourceTransform()) { + m_resourceTransform = std::make_unique<mbgl::Actor<mbgl::ResourceTransform>>(*mbgl::Scheduler::GetCurrent(), + [callback = settings.resourceTransform()] (mbgl::Resource::Kind, const std::string &&url_) -> std::string { + return callback(std::move(url_)); + }); + auto fs = mbgl::FileSource::getSharedFileSource(resourceOptions); + std::static_pointer_cast<mbgl::DefaultFileSource>(fs)->setResourceTransform(m_resourceTransform->self()); + } // Needs to be Queued to give time to discard redundant draw calls via the `renderQueued` flag. connect(this, SIGNAL(needsRendering()), q, SIGNAL(needsRendering()), Qt::QueuedConnection); diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp index 7157df0aba..6a5b5ce04f 100644 --- a/platform/qt/src/qmapboxgl_p.hpp +++ b/platform/qt/src/qmapboxgl_p.hpp @@ -7,7 +7,6 @@ #include <mbgl/actor/actor.hpp> #include <mbgl/map/map.hpp> #include <mbgl/renderer/renderer_frontend.hpp> -#include <mbgl/storage/default_file_source.hpp> #include <mbgl/storage/resource_transform.hpp> #include <mbgl/util/default_thread_pool.hpp> #include <mbgl/util/geo.hpp> @@ -57,7 +56,6 @@ private: std::shared_ptr<mbgl::UpdateParameters> m_updateParameters; std::unique_ptr<QMapboxGLMapObserver> m_mapObserver; - std::shared_ptr<mbgl::DefaultFileSource> m_fileSourceObj; std::shared_ptr<mbgl::ThreadPool> m_threadPool; std::unique_ptr<QMapboxGLMapRenderer> m_mapRenderer; std::unique_ptr<mbgl::Actor<mbgl::ResourceTransform>> m_resourceTransform; diff --git a/src/core-files.json b/src/core-files.json index e78f6232c3..139b93e368 100644 --- a/src/core-files.json +++ b/src/core-files.json @@ -143,8 +143,10 @@ "src/mbgl/sprite/sprite_loader.cpp", "src/mbgl/sprite/sprite_loader_worker.cpp", "src/mbgl/sprite/sprite_parser.cpp", + "src/mbgl/storage/file_source.cpp", "src/mbgl/storage/network_status.cpp", "src/mbgl/storage/resource.cpp", + "src/mbgl/storage/resource_options.cpp", "src/mbgl/storage/resource_transform.cpp", "src/mbgl/storage/response.cpp", "src/mbgl/style/conversion/color_ramp_property_value.cpp", @@ -358,6 +360,7 @@ "mbgl/storage/offline.hpp": "include/mbgl/storage/offline.hpp", "mbgl/storage/online_file_source.hpp": "include/mbgl/storage/online_file_source.hpp", "mbgl/storage/resource.hpp": "include/mbgl/storage/resource.hpp", + "mbgl/storage/resource_options.hpp": "include/mbgl/storage/resource_options.hpp", "mbgl/storage/resource_transform.hpp": "include/mbgl/storage/resource_transform.hpp", "mbgl/storage/response.hpp": "include/mbgl/storage/response.hpp", "mbgl/style/color_ramp_property_value.hpp": "include/mbgl/style/color_ramp_property_value.hpp", diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp index ab22404c15..345171b96e 100644 --- a/src/mbgl/annotation/annotation_manager.cpp +++ b/src/mbgl/annotation/annotation_manager.cpp @@ -10,7 +10,6 @@ #include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/layers/symbol_layer_impl.hpp> #include <mbgl/style/expression/dsl.hpp> -#include <mbgl/storage/file_source.hpp> #include <boost/function_output_iterator.hpp> diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp index e8237cca74..24b2435923 100644 --- a/src/mbgl/map/map.cpp +++ b/src/mbgl/map/map.cpp @@ -31,10 +31,13 @@ Map::Map(RendererFrontend& frontend, MapObserver& observer, const Size size, const float pixelRatio, - FileSource& fileSource, Scheduler& scheduler, - const MapOptions& mapOptions) - : impl(std::make_unique<Impl>(frontend, observer, fileSource, scheduler, size, pixelRatio, mapOptions)) {} + const MapOptions& mapOptions, + const ResourceOptions& resourceOptions) + : impl(std::make_unique<Impl>(frontend, observer, scheduler, size, pixelRatio, + FileSource::getSharedFileSource(resourceOptions), mapOptions)) {} + +Map::Map(std::unique_ptr<Impl> impl_) : impl(std::move(impl_)) {} Map::~Map() = default; diff --git a/src/mbgl/map/map_impl.cpp b/src/mbgl/map/map_impl.cpp index fbceff559f..348e26700f 100644 --- a/src/mbgl/map/map_impl.cpp +++ b/src/mbgl/map/map_impl.cpp @@ -1,6 +1,7 @@ #include <mbgl/layermanager/layer_manager.hpp> #include <mbgl/map/map_impl.hpp> #include <mbgl/renderer/update_parameters.hpp> +#include <mbgl/storage/file_source.hpp> #include <mbgl/style/style_impl.hpp> #include <mbgl/util/exception.hpp> @@ -8,20 +9,20 @@ namespace mbgl { Map::Impl::Impl(RendererFrontend& frontend_, MapObserver& observer_, - FileSource& fileSource_, Scheduler& scheduler_, Size size_, float pixelRatio_, + std::shared_ptr<FileSource> fileSource_, const MapOptions& mapOptions) : observer(observer_), rendererFrontend(frontend_), - fileSource(fileSource_), scheduler(scheduler_), transform(observer, mapOptions.constrainMode(), mapOptions.viewportMode()), mode(mapOptions.mapMode()), pixelRatio(pixelRatio_), crossSourceCollisions(mapOptions.crossSourceCollisions()), - style(std::make_unique<style::Style>(scheduler, fileSource, pixelRatio)), + fileSource(std::move(fileSource_)), + style(std::make_unique<style::Style>(scheduler, *fileSource, pixelRatio)), annotationManager(*style) { style->impl->setObserver(this); rendererFrontend.setObserver(*this); @@ -65,7 +66,7 @@ void Map::Impl::onUpdate() { style->impl->getSourceImpls(), style->impl->getLayerImpls(), annotationManager, - fileSource, + *fileSource, prefetchZoomDelta, bool(stillImageRequest), crossSourceCollisions diff --git a/src/mbgl/map/map_impl.hpp b/src/mbgl/map/map_impl.hpp index d65fe5aafc..13ffdc02ae 100644 --- a/src/mbgl/map/map_impl.hpp +++ b/src/mbgl/map/map_impl.hpp @@ -1,5 +1,6 @@ #pragma once +#include <mbgl/actor/actor.hpp> #include <mbgl/actor/scheduler.hpp> #include <mbgl/annotation/annotation_manager.hpp> #include <mbgl/map/map.hpp> @@ -9,7 +10,6 @@ #include <mbgl/map/transform.hpp> #include <mbgl/renderer/renderer_frontend.hpp> #include <mbgl/renderer/renderer_observer.hpp> -#include <mbgl/storage/file_source.hpp> #include <mbgl/style/observer.hpp> #include <mbgl/style/source.hpp> #include <mbgl/style/style.hpp> @@ -17,6 +17,9 @@ namespace mbgl { +class FileSource; +class ResourceTransform; + struct StillImageRequest { StillImageRequest(Map::StillImageCallback&& callback_) : callback(std::move(callback_)) { @@ -27,7 +30,7 @@ struct StillImageRequest { class Map::Impl : public style::Observer, public RendererObserver { public: - Impl(RendererFrontend&, MapObserver&, FileSource&, Scheduler&, Size size, float pixelRatio, const MapOptions&); + Impl(RendererFrontend&, MapObserver&, Scheduler&, Size size, float pixelRatio, std::shared_ptr<FileSource>, const MapOptions&); ~Impl() final; // StyleObserver @@ -50,7 +53,6 @@ public: MapObserver& observer; RendererFrontend& rendererFrontend; - FileSource& fileSource; Scheduler& scheduler; Transform transform; @@ -61,6 +63,8 @@ public: MapDebugOptions debugOptions { MapDebugOptions::NoDebug }; + std::shared_ptr<FileSource> fileSource; + std::unique_ptr<style::Style> style; AnnotationManager annotationManager; diff --git a/src/mbgl/map/map_options.cpp b/src/mbgl/map/map_options.cpp index 118fcaf3df..ddb3f8e3be 100644 --- a/src/mbgl/map/map_options.cpp +++ b/src/mbgl/map/map_options.cpp @@ -1,7 +1,4 @@ #include <mbgl/map/map_options.hpp> -#include <mbgl/util/constants.hpp> - -#include <cassert> namespace mbgl { @@ -10,9 +7,6 @@ public: MapMode mapMode = MapMode::Continuous; ConstrainMode constrainMode = ConstrainMode::HeightOnly; ViewportMode viewportMode = ViewportMode::Default; - std::string cachePath; - std::string assetRoot; - uint64_t maximumSize{mbgl::util::DEFAULT_MAX_CACHE_SIZE}; bool crossSourceCollisions = true; }; @@ -46,33 +40,6 @@ ViewportMode MapOptions::viewportMode() const { return impl_->viewportMode; } -MapOptions& MapOptions::withCachePath(std::string path) { - impl_->cachePath = std::move(path); - return *this; -} - -const std::string& MapOptions::cachePath() const { - return impl_->cachePath; -} - -MapOptions& MapOptions::withAssetRoot(std::string path) { - impl_->assetRoot = std::move(path); - return *this; -} - -const std::string& MapOptions::assetRoot() const { - return impl_->assetRoot; -} - -MapOptions& MapOptions::withMaximumCacheSize(uint64_t size) { - impl_->maximumSize = size; - return *this; -} - -uint64_t MapOptions::maximumCacheSize() const { - return impl_->maximumSize; -} - MapOptions& MapOptions::withCrossSourceCollisions(bool enableCollisions) { impl_->crossSourceCollisions = enableCollisions; return *this; diff --git a/src/mbgl/storage/asset_file_source.hpp b/src/mbgl/storage/asset_file_source.hpp index 5d98b4e69e..cc15dbb60b 100644 --- a/src/mbgl/storage/asset_file_source.hpp +++ b/src/mbgl/storage/asset_file_source.hpp @@ -10,7 +10,7 @@ template <typename T> class Thread; class AssetFileSource : public FileSource { public: - AssetFileSource(const std::string& assetRoot); + AssetFileSource(const std::string& assetPath); ~AssetFileSource() override; std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override; diff --git a/src/mbgl/storage/file_source.cpp b/src/mbgl/storage/file_source.cpp new file mode 100644 index 0000000000..5854682771 --- /dev/null +++ b/src/mbgl/storage/file_source.cpp @@ -0,0 +1,37 @@ +#include <mbgl/storage/file_source.hpp> +#include <mbgl/storage/resource_options.hpp> +#include <mbgl/util/string.hpp> + +#include <mutex> +#include <map> + +namespace mbgl { + +std::shared_ptr<FileSource> FileSource::getSharedFileSource(const ResourceOptions& options) { + static std::mutex mutex; + static std::map<std::string, std::weak_ptr<mbgl::FileSource>> fileSources; + + std::lock_guard<std::mutex> lock(mutex); + + // Purge entries no longer in use. + for (auto it = fileSources.begin(); it != fileSources.end();) { + it = it->second.expired() ? fileSources.erase(it) : ++it; + } + + const uint64_t context = reinterpret_cast<uint64_t>(options.platformContext()); + const std::string key = options.baseURL() + '|' + options.accessToken() + '|' + options.cachePath() + '|' + util::toString(context); + + std::shared_ptr<mbgl::FileSource> fileSource; + auto tuple = fileSources.find(key); + if (tuple != fileSources.end()) { + fileSource = tuple->second.lock(); + } + + if (!fileSource) { + fileSources[key] = fileSource = createPlatformFileSource(options); + } + + return fileSource; +} + +} // namespace mbgl diff --git a/src/mbgl/storage/resource_options.cpp b/src/mbgl/storage/resource_options.cpp new file mode 100644 index 0000000000..ce82b51a14 --- /dev/null +++ b/src/mbgl/storage/resource_options.cpp @@ -0,0 +1,73 @@ +#include <mbgl/storage/resource_options.hpp> +#include <mbgl/util/constants.hpp> + +namespace mbgl { + +class ResourceOptions::Impl { +public: + std::string accessToken; + std::string baseURL = mbgl::util::API_BASE_URL; + std::string cachePath = ":memory:"; + std::string assetPath = "."; + uint64_t maximumSize = mbgl::util::DEFAULT_MAX_CACHE_SIZE; + void* platformContext = nullptr; +}; + +ResourceOptions::ResourceOptions() : impl_(std::make_shared<ResourceOptions::Impl>()) {} +ResourceOptions::~ResourceOptions() = default; + +ResourceOptions& ResourceOptions::withAccessToken(std::string token) { + impl_->accessToken = std::move(token); + return *this; +} + +const std::string& ResourceOptions::accessToken() const { + return impl_->accessToken; +} + +ResourceOptions& ResourceOptions::withBaseURL(std::string url) { + impl_->baseURL = std::move(url); + return *this; +} + +const std::string& ResourceOptions::baseURL() const { + return impl_->baseURL; +} + +ResourceOptions& ResourceOptions::withCachePath(std::string path) { + impl_->cachePath = std::move(path); + return *this; +} + +const std::string& ResourceOptions::cachePath() const { + return impl_->cachePath; +} + +ResourceOptions& ResourceOptions::withAssetPath(std::string path) { + impl_->assetPath = std::move(path); + return *this; +} + +const std::string& ResourceOptions::assetPath() const { + return impl_->assetPath; +} + +ResourceOptions& ResourceOptions::withMaximumCacheSize(uint64_t size) { + impl_->maximumSize = size; + return *this; +} + +uint64_t ResourceOptions::maximumCacheSize() const { + return impl_->maximumSize; +} + +ResourceOptions& ResourceOptions::withPlatformContext(void* context) { + impl_->platformContext = context; + return *this; +} + +void* ResourceOptions::platformContext() const { + return impl_->platformContext; +} + +} // namespace mbgl diff --git a/src/mbgl/style/sources/raster_dem_source.cpp b/src/mbgl/style/sources/raster_dem_source.cpp index dc9feb8eeb..bb745561b1 100644 --- a/src/mbgl/style/sources/raster_dem_source.cpp +++ b/src/mbgl/style/sources/raster_dem_source.cpp @@ -3,7 +3,6 @@ #include <mbgl/style/source_observer.hpp> #include <mbgl/style/conversion/json.hpp> #include <mbgl/style/conversion/tileset.hpp> -#include <mbgl/storage/file_source.hpp> #include <mbgl/util/mapbox.hpp> namespace mbgl { @@ -13,7 +12,5 @@ RasterDEMSource::RasterDEMSource(std::string id, variant<std::string, Tileset> u : RasterSource(std::move(id), urlOrTileset_, tileSize, SourceType::RasterDEM){ } - - } // namespace style } // namespace mbgl diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index c8498976b8..d0b55a17d4 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -13,7 +13,6 @@ #include <mbgl/renderer/query.hpp> #include <mbgl/text/glyph_atlas.hpp> #include <mbgl/renderer/image_atlas.hpp> -#include <mbgl/storage/file_source.hpp> #include <mbgl/geometry/feature_index.hpp> #include <mbgl/map/transform_state.hpp> #include <mbgl/util/logging.hpp> diff --git a/src/mbgl/tile/raster_dem_tile.cpp b/src/mbgl/tile/raster_dem_tile.cpp index ba961853d0..224c5c9062 100644 --- a/src/mbgl/tile/raster_dem_tile.cpp +++ b/src/mbgl/tile/raster_dem_tile.cpp @@ -5,7 +5,6 @@ #include <mbgl/style/source.hpp> #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> -#include <mbgl/storage/file_source.hpp> #include <mbgl/renderer/tile_parameters.hpp> #include <mbgl/renderer/buckets/hillshade_bucket.hpp> #include <mbgl/actor/scheduler.hpp> diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp index 22561ec11d..ff02301021 100644 --- a/src/mbgl/tile/raster_tile.cpp +++ b/src/mbgl/tile/raster_tile.cpp @@ -5,7 +5,6 @@ #include <mbgl/style/source.hpp> #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> -#include <mbgl/storage/file_source.hpp> #include <mbgl/renderer/tile_parameters.hpp> #include <mbgl/renderer/buckets/raster_bucket.hpp> #include <mbgl/actor/scheduler.hpp> diff --git a/test/api/annotations.test.cpp b/test/api/annotations.test.cpp index aad85f8d57..2a9737e10b 100644 --- a/test/api/annotations.test.cpp +++ b/test/api/annotations.test.cpp @@ -1,11 +1,11 @@ #include <mbgl/test/util.hpp> #include <mbgl/test/stub_file_source.hpp> +#include <mbgl/test/map_adapter.hpp> #include <mbgl/util/default_thread_pool.hpp> #include <mbgl/annotation/annotation.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/image.hpp> -#include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/util/io.hpp> #include <mbgl/util/run_loop.hpp> @@ -28,13 +28,12 @@ std::unique_ptr<style::Image> namedMarker(const std::string& name) { class AnnotationTest { public: util::RunLoop loop; - StubFileSource fileSource; ThreadPool threadPool { 4 }; float pixelRatio { 1 }; HeadlessFrontend frontend { pixelRatio, threadPool }; - Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, - threadPool, MapOptions().withMapMode(MapMode::Static)}; + MapAdapter map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, std::make_shared<StubFileSource>(), + threadPool, MapOptions().withMapMode(MapMode::Static)}; void checkRendering(const char * name) { test::checkImage(std::string("test/fixtures/annotations/") + name, diff --git a/test/api/api_misuse.test.cpp b/test/api/api_misuse.test.cpp index 2ccfb0a7ff..6fc04ab26f 100644 --- a/test/api/api_misuse.test.cpp +++ b/test/api/api_misuse.test.cpp @@ -1,12 +1,11 @@ #include <mbgl/test/util.hpp> #include <mbgl/test/stub_file_source.hpp> #include <mbgl/test/fixture_log_observer.hpp> +#include <mbgl/test/map_adapter.hpp> -#include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/renderer/backend_scope.hpp> #include <mbgl/gl/headless_frontend.hpp> -#include <mbgl/storage/online_file_source.hpp> #include <mbgl/util/default_thread_pool.hpp> #include <mbgl/util/exception.hpp> #include <mbgl/util/run_loop.hpp> @@ -22,14 +21,13 @@ TEST(API, RenderWithoutCallback) { util::RunLoop loop; - StubFileSource fileSource; ThreadPool threadPool(4); float pixelRatio { 1 }; HeadlessFrontend frontend { pixelRatio, threadPool }; - auto map = std::make_unique<Map>(frontend, MapObserver::nullObserver(), frontend.getSize(), - pixelRatio, fileSource, threadPool, - MapOptions().withMapMode(MapMode::Static)); + auto map = std::make_unique<MapAdapter>(frontend, MapObserver::nullObserver(), frontend.getSize(), + pixelRatio, std::make_shared<StubFileSource>(), threadPool, + MapOptions().withMapMode(MapMode::Static)); map->renderStill(nullptr); // Force Map thread to join. diff --git a/test/api/custom_geometry_source.test.cpp b/test/api/custom_geometry_source.test.cpp index 6959a36f15..58af09c1ac 100644 --- a/test/api/custom_geometry_source.test.cpp +++ b/test/api/custom_geometry_source.test.cpp @@ -3,8 +3,8 @@ #include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/util/shared_thread_pool.hpp> -#include <mbgl/storage/default_file_source.hpp> #include <mbgl/gl/headless_frontend.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/sources/custom_geometry_source.hpp> #include <mbgl/style/layers/fill_layer.hpp> @@ -20,12 +20,12 @@ using namespace mbgl::style; TEST(CustomGeometrySource, Grid) { util::RunLoop loop; - DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets"); auto threadPool = sharedThreadPool(); float pixelRatio { 1 }; HeadlessFrontend frontend { pixelRatio, *threadPool }; - Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, - *threadPool, MapOptions().withMapMode(MapMode::Static)); + Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, *threadPool, + MapOptions().withMapMode(MapMode::Static), + ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets")); map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json")); map.jumpTo(CameraOptions().withCenter(LatLng { 37.8, -122.5 }).withZoom(10.0)); diff --git a/test/api/custom_layer.test.cpp b/test/api/custom_layer.test.cpp index 18c6dc1692..e16d2852ec 100644 --- a/test/api/custom_layer.test.cpp +++ b/test/api/custom_layer.test.cpp @@ -4,9 +4,9 @@ #include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/util/default_thread_pool.hpp> -#include <mbgl/storage/default_file_source.hpp> #include <mbgl/gl/defines.hpp> #include <mbgl/gl/headless_frontend.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/layers/custom_layer.hpp> #include <mbgl/style/layers/fill_layer.hpp> @@ -90,12 +90,12 @@ public: TEST(CustomLayer, Basic) { util::RunLoop loop; - DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets"); ThreadPool threadPool(4); float pixelRatio { 1 }; HeadlessFrontend frontend { pixelRatio, threadPool }; - Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, - threadPool, MapOptions().withMapMode(MapMode::Static)); + Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, threadPool, + MapOptions().withMapMode(MapMode::Static), + ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets")); map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json")); map.jumpTo(CameraOptions().withCenter(LatLng { 37.8, -122.5 }).withZoom(10.0)); map.getStyle().addLayer(std::make_unique<CustomLayer>( diff --git a/test/api/query.test.cpp b/test/api/query.test.cpp index 5567eabc73..b4297bfe82 100644 --- a/test/api/query.test.cpp +++ b/test/api/query.test.cpp @@ -1,4 +1,5 @@ -#include <mbgl/map/map.hpp> +#include <mbgl/test/map_adapter.hpp> + #include <mbgl/map/map_options.hpp> #include <mbgl/util/default_thread_pool.hpp> #include <mbgl/test/stub_file_source.hpp> @@ -33,16 +34,16 @@ public: } util::RunLoop loop; - StubFileSource fileSource; + std::shared_ptr<StubFileSource> fileSource = std::make_shared<StubFileSource>(); ThreadPool threadPool { 4 }; float pixelRatio { 1 }; HeadlessFrontend frontend { pixelRatio, threadPool }; - Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, - threadPool, MapOptions().withMapMode(MapMode::Static)}; + MapAdapter map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, + threadPool, MapOptions().withMapMode(MapMode::Static)}; }; std::vector<Feature> getTopClusterFeature(QueryTest& test) { - test.fileSource.sourceResponse = [&] (const Resource& resource) { + test.fileSource->sourceResponse = [&] (const Resource& resource) { EXPECT_EQ("http://url"s, resource.url); Response response; response.data = std::make_unique<std::string>(util::read_file("test/fixtures/supercluster/places.json"s)); @@ -54,7 +55,7 @@ std::vector<Feature> getTopClusterFeature(QueryTest& test) { options.cluster = true; auto source = std::make_unique<GeoJSONSource>("cluster_source"s, options); source->setURL("http://url"s); - source->loadDescription(test.fileSource); + source->loadDescription(*test.fileSource); auto clusterLayer = std::make_unique<SymbolLayer>("cluster_layer"s, "cluster_source"s); clusterLayer->setIconImage("test-icon"s); diff --git a/test/api/recycle_map.cpp b/test/api/recycle_map.cpp index db576b4cf6..7d14bd14de 100644 --- a/test/api/recycle_map.cpp +++ b/test/api/recycle_map.cpp @@ -1,11 +1,10 @@ #include <mbgl/test/util.hpp> #include <mbgl/test/stub_file_source.hpp> +#include <mbgl/test/map_adapter.hpp> #include <mbgl/gl/headless_frontend.hpp> -#include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/renderer/backend_scope.hpp> -#include <mbgl/storage/online_file_source.hpp> #include <mbgl/style/layers/symbol_layer.hpp> #include <mbgl/style/sources/geojson_source.hpp> #include <mbgl/style/image.hpp> @@ -24,14 +23,13 @@ using namespace mbgl::style; TEST(API, RecycleMapUpdateImages) { util::RunLoop loop; - StubFileSource fileSource; ThreadPool threadPool(4); float pixelRatio { 1 }; HeadlessFrontend frontend { pixelRatio, threadPool }; - auto map = std::make_unique<Map>(frontend, MapObserver::nullObserver(), frontend.getSize(), - pixelRatio, fileSource, threadPool, - MapOptions().withMapMode(MapMode::Static)); + auto map = std::make_unique<MapAdapter>(frontend, MapObserver::nullObserver(), frontend.getSize(), + pixelRatio, std::make_shared<StubFileSource>(), threadPool, + MapOptions().withMapMode(MapMode::Static)); EXPECT_TRUE(map); diff --git a/test/gl/context.test.cpp b/test/gl/context.test.cpp index 3c055c2ce0..ff9b2ecac2 100644 --- a/test/gl/context.test.cpp +++ b/test/gl/context.test.cpp @@ -5,9 +5,9 @@ #include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/util/default_thread_pool.hpp> -#include <mbgl/storage/default_file_source.hpp> #include <mbgl/gl/defines.hpp> #include <mbgl/gl/headless_frontend.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/style/style.hpp> #include <mbgl/style/layers/custom_layer.hpp> #include <mbgl/style/layers/fill_layer.hpp> @@ -86,14 +86,14 @@ struct Buffer { TEST(GLContextMode, Shared) { util::RunLoop loop; - DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets"); ThreadPool threadPool(4); float pixelRatio { 1 }; HeadlessFrontend frontend { pixelRatio, threadPool, {}, GLContextMode::Shared }; - Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, - fileSource, threadPool, MapOptions().withMapMode(MapMode::Static)); + Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, threadPool, + MapOptions().withMapMode(MapMode::Static), + ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets")); map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json")); map.jumpTo(CameraOptions().withCenter(LatLng { 37.8, -122.5 }).withZoom(10.0)); diff --git a/test/map/map.test.cpp b/test/map/map.test.cpp index 410a7e76af..c06fa53744 100644 --- a/test/map/map.test.cpp +++ b/test/map/map.test.cpp @@ -3,12 +3,13 @@ #include <mbgl/test/stub_map_observer.hpp> #include <mbgl/test/fake_file_source.hpp> #include <mbgl/test/fixture_log_observer.hpp> +#include <mbgl/test/map_adapter.hpp> -#include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/gl/context.hpp> #include <mbgl/gl/headless_frontend.hpp> #include <mbgl/util/default_thread_pool.hpp> +#include <mbgl/storage/resource_options.hpp> #include <mbgl/storage/network_status.hpp> #include <mbgl/storage/default_file_source.hpp> #include <mbgl/storage/online_file_source.hpp> @@ -31,27 +32,26 @@ template <class FileSource = StubFileSource> class MapTest { public: util::RunLoop runLoop; - FileSource fileSource; + std::shared_ptr<FileSource> fileSource; ThreadPool threadPool { 4 }; StubMapObserver observer; HeadlessFrontend frontend; - Map map; + MapAdapter map; MapTest(float pixelRatio = 1, MapMode mode = MapMode::Static) - : frontend(pixelRatio, threadPool) + : fileSource(std::make_shared<FileSource>()) + , frontend(pixelRatio, threadPool) , map(frontend, observer, frontend.getSize(), pixelRatio, - fileSource, threadPool, MapOptions().withMapMode(mode)) { - } + fileSource, threadPool, MapOptions().withMapMode(mode)) {} template <typename T = FileSource> - MapTest(const std::string& cachePath, const std::string& assetRoot, + MapTest(const std::string& cachePath, const std::string& assetPath, float pixelRatio = 1, MapMode mode = MapMode::Static, typename std::enable_if<std::is_same<T, DefaultFileSource>::value>::type* = 0) - : fileSource { cachePath, assetRoot } + : fileSource(std::make_shared<T>(cachePath, assetPath)) , frontend(pixelRatio, threadPool) , map(frontend, observer, frontend.getSize(), pixelRatio, - fileSource, threadPool, MapOptions().withMapMode(mode)) { - } + fileSource, threadPool, MapOptions().withMapMode(mode)) {} }; TEST(Map, RendererState) { @@ -235,12 +235,12 @@ TEST(Map, Offline) { }; const std::string prefix = "http://127.0.0.1:3000/"; - test.fileSource.put(Resource::style(prefix + "style.json"), expiredItem("style.json")); - test.fileSource.put(Resource::source(prefix + "streets.json"), expiredItem("streets.json")); - test.fileSource.put(Resource::spriteJSON(prefix + "sprite", 1.0), expiredItem("sprite.json")); - test.fileSource.put(Resource::spriteImage(prefix + "sprite", 1.0), expiredItem("sprite.png")); - test.fileSource.put(Resource::tile(prefix + "{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), expiredItem("0-0-0.vector.pbf")); - test.fileSource.put(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), expiredItem("glyph.pbf")); + test.fileSource->put(Resource::style(prefix + "style.json"), expiredItem("style.json")); + test.fileSource->put(Resource::source(prefix + "streets.json"), expiredItem("streets.json")); + test.fileSource->put(Resource::spriteJSON(prefix + "sprite", 1.0), expiredItem("sprite.json")); + test.fileSource->put(Resource::spriteImage(prefix + "sprite", 1.0), expiredItem("sprite.png")); + test.fileSource->put(Resource::tile(prefix + "{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), expiredItem("0-0-0.vector.pbf")); + test.fileSource->put(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), expiredItem("glyph.pbf")); NetworkStatus::Set(NetworkStatus::Status::Offline); test.map.getStyle().loadURL(prefix + "style.json"); @@ -334,7 +334,7 @@ TEST(Map, SetStyleInvalidJSON) { TEST(Map, SetStyleInvalidURL) { MapTest<> test; - test.fileSource.styleResponse = [] (const Resource&) { + test.fileSource->styleResponse = [] (const Resource&) { Response response; response.error = std::make_unique<Response::Error>( Response::Error::Reason::Other, @@ -364,14 +364,14 @@ TEST(Map, StyleFresh) { MapTest<FakeFileSource> test; test.map.getStyle().loadURL("mapbox://styles/test"); - EXPECT_EQ(1u, test.fileSource.requests.size()); + EXPECT_EQ(1u, test.fileSource->requests.size()); Response response; response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json")); response.expires = Timestamp::max(); - test.fileSource.respond(Resource::Style, response); - EXPECT_EQ(1u, test.fileSource.requests.size()); + test.fileSource->respond(Resource::Style, response); + EXPECT_EQ(1u, test.fileSource->requests.size()); } TEST(Map, StyleExpired) { @@ -382,31 +382,31 @@ TEST(Map, StyleExpired) { MapTest<FakeFileSource> test; test.map.getStyle().loadURL("mapbox://styles/test"); - EXPECT_EQ(1u, test.fileSource.requests.size()); + EXPECT_EQ(1u, test.fileSource->requests.size()); Response response; response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json")); response.expires = util::now() - 1h; - test.fileSource.respond(Resource::Style, response); - EXPECT_EQ(1u, test.fileSource.requests.size()); + test.fileSource->respond(Resource::Style, response); + EXPECT_EQ(1u, test.fileSource->requests.size()); // Mutate layer. From now on, sending a response to the style won't overwrite it anymore, but // we should continue to wait for a fresh response. test.map.getStyle().addLayer(std::make_unique<style::BackgroundLayer>("bg")); - EXPECT_EQ(1u, test.fileSource.requests.size()); + EXPECT_EQ(1u, test.fileSource->requests.size()); // Send another expired response, and confirm that we didn't overwrite the style, but continue // to wait for a fresh response. - test.fileSource.respond(Resource::Style, response); - EXPECT_EQ(1u, test.fileSource.requests.size()); + test.fileSource->respond(Resource::Style, response); + EXPECT_EQ(1u, test.fileSource->requests.size()); EXPECT_NE(nullptr, test.map.getStyle().getLayer("bg")); // Send a fresh response, and confirm that we didn't overwrite the style, but continue to wait // for a fresh response. response.expires = util::now() + 1h; - test.fileSource.respond(Resource::Style, response); - EXPECT_EQ(1u, test.fileSource.requests.size()); + test.fileSource->respond(Resource::Style, response); + EXPECT_EQ(1u, test.fileSource->requests.size()); EXPECT_NE(nullptr, test.map.getStyle().getLayer("bg")); } @@ -418,20 +418,20 @@ TEST(Map, StyleExpiredWithAnnotations) { MapTest<FakeFileSource> test; test.map.getStyle().loadURL("mapbox://styles/test"); - EXPECT_EQ(1u, test.fileSource.requests.size()); + EXPECT_EQ(1u, test.fileSource->requests.size()); Response response; response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json")); response.expires = util::now() - 1h; - test.fileSource.respond(Resource::Style, response); - EXPECT_EQ(1u, test.fileSource.requests.size()); + test.fileSource->respond(Resource::Style, response); + EXPECT_EQ(1u, test.fileSource->requests.size()); test.map.addAnnotation(LineAnnotation { LineString<double> {{ { 0, 0 }, { 10, 10 } }} }); - EXPECT_EQ(1u, test.fileSource.requests.size()); + EXPECT_EQ(1u, test.fileSource->requests.size()); - test.fileSource.respond(Resource::Style, response); - EXPECT_EQ(1u, test.fileSource.requests.size()); + test.fileSource->respond(Resource::Style, response); + EXPECT_EQ(1u, test.fileSource->requests.size()); } TEST(Map, StyleExpiredWithRender) { @@ -442,20 +442,20 @@ TEST(Map, StyleExpiredWithRender) { MapTest<FakeFileSource> test; test.map.getStyle().loadURL("mapbox://styles/test"); - EXPECT_EQ(1u, test.fileSource.requests.size()); + EXPECT_EQ(1u, test.fileSource->requests.size()); Response response; response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/empty.json")); response.expires = util::now() - 1h; - test.fileSource.respond(Resource::Style, response); - EXPECT_EQ(1u, test.fileSource.requests.size()); + test.fileSource->respond(Resource::Style, response); + EXPECT_EQ(1u, test.fileSource->requests.size()); test.frontend.render(test.map); - EXPECT_EQ(1u, test.fileSource.requests.size()); + EXPECT_EQ(1u, test.fileSource->requests.size()); - test.fileSource.respond(Resource::Style, response); - EXPECT_EQ(1u, test.fileSource.requests.size()); + test.fileSource->respond(Resource::Style, response); + EXPECT_EQ(1u, test.fileSource->requests.size()); } TEST(Map, StyleEarlyMutation) { @@ -468,9 +468,9 @@ TEST(Map, StyleEarlyMutation) { Response response; response.data = std::make_shared<std::string>(util::read_file("test/fixtures/api/water.json")); - test.fileSource.respond(Resource::Style, response); + test.fileSource->respond(Resource::Style, response); - EXPECT_EQ(1u, test.fileSource.requests.size()); + EXPECT_EQ(1u, test.fileSource->requests.size()); EXPECT_NE(nullptr, test.map.getStyle().getLayer("water")); } @@ -592,7 +592,7 @@ TEST(Map, DisabledSources) { MapTest<> test; // Always load the same image tile for raster layers. - test.fileSource.response = [] (const Resource& res) -> optional<Response> { + test.fileSource->response = [] (const Resource& res) -> optional<Response> { if (res.url == "asset://tile.png") { Response response; response.data = std::make_shared<std::string>( @@ -668,7 +668,7 @@ TEST(Map, DontLoadUnneededTiles) { using Tiles = std::unordered_set<std::string>; Tiles tiles; - test.fileSource.tileResponse = [&](const Resource& rsc) { + test.fileSource->tileResponse = [&](const Resource& rsc) { tiles.emplace(rsc.url); Response res; res.noContent = true; @@ -698,7 +698,6 @@ TEST(Map, DontLoadUnneededTiles) { TEST(Map, TEST_DISABLED_ON_CI(ContinuousRendering)) { util::RunLoop runLoop; ThreadPool threadPool { 4 }; - DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets"); float pixelRatio { 1 }; using namespace std::chrono_literals; @@ -723,8 +722,9 @@ TEST(Map, TEST_DISABLED_ON_CI(ContinuousRendering)) { }); }; - Map map(frontend, observer, frontend.getSize(), pixelRatio, fileSource, - threadPool, MapOptions().withMapMode(MapMode::Continuous)); + Map map(frontend, observer, frontend.getSize(), pixelRatio, threadPool, + MapOptions().withMapMode(MapMode::Continuous), + ResourceOptions().withCachePath(":memory:").withAssetPath("test/fixtures/api/assets")); map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json")); runLoop.run(); @@ -739,7 +739,7 @@ TEST(Map, NoContentTiles) { Response response; response.noContent = true; response.expires = util::now() + 1h; - test.fileSource.put(Resource::tile("http://example.com/{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, + test.fileSource->put(Resource::tile("http://example.com/{z}-{x}-{y}.vector.pbf", 1.0, 0, 0, 0, Tileset::Scheme::XYZ), response); @@ -776,7 +776,7 @@ TEST(Map, NoContentTiles) { TEST(Map, Issue12432) { MapTest<> test { 1, MapMode::Continuous }; - test.fileSource.tileResponse = [&](const Resource&) { + test.fileSource->tileResponse = [&](const Resource&) { Response result; result.data = std::make_shared<std::string>(util::read_file("test/fixtures/map/issue12432/0-0-0.mvt")); return result; diff --git a/test/map/prefetch.test.cpp b/test/map/prefetch.test.cpp index dfde3a779b..2830045983 100644 --- a/test/map/prefetch.test.cpp +++ b/test/map/prefetch.test.cpp @@ -1,11 +1,10 @@ #include <mbgl/test/util.hpp> #include <mbgl/test/stub_file_source.hpp> #include <mbgl/test/stub_map_observer.hpp> +#include <mbgl/test/map_adapter.hpp> -#include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/gl/headless_frontend.hpp> -#include <mbgl/storage/default_file_source.hpp> #include <mbgl/style/style.hpp> #include <mbgl/util/default_thread_pool.hpp> #include <mbgl/util/image.hpp> @@ -24,7 +23,7 @@ using namespace std::chrono_literals; TEST(Map, PrefetchTiles) { util::RunLoop runLoop; ThreadPool threadPool(4); - StubFileSource fileSource; + std::shared_ptr<StubFileSource> fileSource = std::make_shared<StubFileSource>(); util::Timer emergencyShutoff; emergencyShutoff.start(10s, 0s, [&] { @@ -38,12 +37,12 @@ TEST(Map, PrefetchTiles) { }; HeadlessFrontend frontend { { 512, 512 }, 1, threadPool }; - Map map(frontend, observer, frontend.getSize(), 1, fileSource, threadPool, - MapOptions().withMapMode(MapMode::Continuous)); + MapAdapter map(frontend, observer, frontend.getSize(), 1, fileSource, threadPool, + MapOptions().withMapMode(MapMode::Continuous)); std::vector<int> tiles; - fileSource.response = [&] (const Resource& res) -> optional<Response> { + fileSource->response = [&] (const Resource& res) -> optional<Response> { static std::string tile = util::read_file("test/fixtures/map/prefetch/tile.png"); auto zoom = std::stoi(res.url); diff --git a/test/renderer/image_manager.test.cpp b/test/renderer/image_manager.test.cpp index 4a838d0f9c..20451827ce 100644 --- a/test/renderer/image_manager.test.cpp +++ b/test/renderer/image_manager.test.cpp @@ -1,6 +1,5 @@ #include <mbgl/test/util.hpp> #include <mbgl/test/fixture_log_observer.hpp> -#include <mbgl/test/stub_file_source.hpp> #include <mbgl/test/stub_style_observer.hpp> #include <mbgl/renderer/image_manager.hpp> diff --git a/test/src/mbgl/test/map_adapter.hpp b/test/src/mbgl/test/map_adapter.hpp new file mode 100644 index 0000000000..e0fc449f48 --- /dev/null +++ b/test/src/mbgl/test/map_adapter.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include <mbgl/map/map.hpp> +#include <mbgl/map/map_impl.hpp> + +namespace mbgl { + +class FileSource; + +// Non-public version of mbgl::Map that accepts a file source as parameter. +class MapAdapter : public Map { +public: + explicit MapAdapter(RendererFrontend& frontend, + MapObserver& observer, + Size size, + float ratio, + std::shared_ptr<FileSource> fileSource, + Scheduler& scheduler, + const MapOptions& options) + : Map(std::make_unique<Map::Impl>(frontend, observer, scheduler, size, ratio, std::move(fileSource), options)) {} +}; + +} // namespace mbgl diff --git a/test/test-files.json b/test/test-files.json index 498237e072..58970689be 100644 --- a/test/test-files.json +++ b/test/test-files.json @@ -114,6 +114,7 @@ "mbgl/test/fake_file_source.hpp": "test/src/mbgl/test/fake_file_source.hpp", "mbgl/test/fixture_log_observer.hpp": "test/src/mbgl/test/fixture_log_observer.hpp", "mbgl/test/getrss.hpp": "test/src/mbgl/test/getrss.hpp", + "mbgl/test/map_adapter.hpp": "test/src/mbgl/test/map_adapter.hpp", "mbgl/test/mock.hpp": "test/src/mbgl/test/mock.hpp", "mbgl/test/sqlite3_test_fs.hpp": "test/src/mbgl/test/sqlite3_test_fs.hpp", "mbgl/test/stub_file_source.hpp": "test/src/mbgl/test/stub_file_source.hpp", diff --git a/test/text/local_glyph_rasterizer.test.cpp b/test/text/local_glyph_rasterizer.test.cpp index d0fdb5ee57..a266021f25 100644 --- a/test/text/local_glyph_rasterizer.test.cpp +++ b/test/text/local_glyph_rasterizer.test.cpp @@ -1,6 +1,7 @@ #include <mbgl/test/util.hpp> #include <mbgl/test/stub_file_source.hpp> -#include <mbgl/map/map.hpp> +#include <mbgl/test/map_adapter.hpp> + #include <mbgl/map/map_options.hpp> #include <mbgl/util/io.hpp> #include <mbgl/util/run_loop.hpp> @@ -38,12 +39,12 @@ public: } util::RunLoop loop; - StubFileSource fileSource; + std::shared_ptr<StubFileSource> fileSource = std::make_shared<StubFileSource>(); ThreadPool threadPool { 4 }; float pixelRatio { 1 }; HeadlessFrontend frontend; - Map map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, - threadPool, MapOptions().withMapMode(MapMode::Static)}; + MapAdapter map { frontend, MapObserver::nullObserver(), frontend.getSize(), pixelRatio, fileSource, + threadPool, MapOptions().withMapMode(MapMode::Static)}; void checkRendering(const char * name) { test::checkImage(std::string("test/fixtures/local_glyphs/") + name, @@ -59,7 +60,7 @@ public: TEST(LocalGlyphRasterizer, PingFang) { LocalGlyphRasterizerTest test(std::string("PingFang")); - test.fileSource.glyphsResponse = [&] (const Resource& resource) { + test.fileSource->glyphsResponse = [&] (const Resource& resource) { EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); Response response; response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf")); @@ -80,7 +81,7 @@ TEST(LocalGlyphRasterizer, NoLocal) { // the output should just contain basic latin characters. LocalGlyphRasterizerTest test({}); - test.fileSource.glyphsResponse = [&] (const Resource& resource) { + test.fileSource->glyphsResponse = [&] (const Resource& resource) { EXPECT_EQ(Resource::Kind::Glyphs, resource.kind); Response response; response.data = std::make_shared<std::string>(util::read_file("test/fixtures/resources/glyphs.pbf")); diff --git a/test/util/memory.test.cpp b/test/util/memory.test.cpp index 36bed57ab5..c1ae597986 100644 --- a/test/util/memory.test.cpp +++ b/test/util/memory.test.cpp @@ -1,8 +1,8 @@ #include <mbgl/test/stub_file_source.hpp> #include <mbgl/test/getrss.hpp> #include <mbgl/test/util.hpp> +#include <mbgl/test/map_adapter.hpp> -#include <mbgl/map/map.hpp> #include <mbgl/map/map_options.hpp> #include <mbgl/gl/headless_frontend.hpp> #include <mbgl/util/default_thread_pool.hpp> @@ -16,6 +16,7 @@ #include <string> #include <unordered_map> #include <utility> +#include <memory> #include <cstdlib> #include <unistd.h> @@ -26,16 +27,16 @@ using namespace std::literals::string_literals; class MemoryTest { public: MemoryTest() { - fileSource.styleResponse = [&](const Resource& res) { return response("style_" + getType(res) + ".json");}; - fileSource.tileResponse = [&](const Resource& res) { return response(getType(res) + ".tile"); }; - fileSource.sourceResponse = [&](const Resource& res) { return response("source_" + getType(res) + ".json"); }; - fileSource.glyphsResponse = [&](const Resource&) { return response("glyphs.pbf"); }; - fileSource.spriteJSONResponse = [&](const Resource&) { return response("sprite.json"); }; - fileSource.spriteImageResponse = [&](const Resource&) { return response("sprite.png"); }; + fileSource->styleResponse = [&](const Resource& res) { return response("style_" + getType(res) + ".json");}; + fileSource->tileResponse = [&](const Resource& res) { return response(getType(res) + ".tile"); }; + fileSource->sourceResponse = [&](const Resource& res) { return response("source_" + getType(res) + ".json"); }; + fileSource->glyphsResponse = [&](const Resource&) { return response("glyphs.pbf"); }; + fileSource->spriteJSONResponse = [&](const Resource&) { return response("sprite.json"); }; + fileSource->spriteImageResponse = [&](const Resource&) { return response("sprite.png"); }; } util::RunLoop runLoop; - StubFileSource fileSource; + std::shared_ptr<StubFileSource> fileSource = std::make_shared<StubFileSource>(); ThreadPool threadPool { 4 }; private: @@ -72,8 +73,8 @@ TEST(Memory, Vector) { float ratio { 2 }; HeadlessFrontend frontend { { 256, 256 }, ratio, test.threadPool }; - Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), ratio, test.fileSource, - test.threadPool, MapOptions().withMapMode(MapMode::Static)); + MapAdapter map(frontend, MapObserver::nullObserver(), frontend.getSize(), ratio, test.fileSource, + test.threadPool, MapOptions().withMapMode(MapMode::Static)); map.jumpTo(CameraOptions().withZoom(16)); map.getStyle().loadURL("mapbox://streets"); @@ -85,8 +86,8 @@ TEST(Memory, Raster) { float ratio { 2 }; HeadlessFrontend frontend { { 256, 256 }, ratio, test.threadPool }; - Map map(frontend, MapObserver::nullObserver(), frontend.getSize(), ratio, test.fileSource, - test.threadPool, MapOptions().withMapMode(MapMode::Static)); + MapAdapter map(frontend, MapObserver::nullObserver(), frontend.getSize(), ratio, test.fileSource, + test.threadPool, MapOptions().withMapMode(MapMode::Static)); map.getStyle().loadURL("mapbox://satellite"); frontend.render(map); @@ -131,7 +132,7 @@ TEST(Memory, Footprint) { } HeadlessFrontend frontend; - Map map; + MapAdapter map; }; // Warm up buffers and cache. |