From 1ae14a55d0c4e815302e605448c02fd1afac93c7 Mon Sep 17 00:00:00 2001 From: Alex Cristici Date: Tue, 16 Jul 2024 01:31:11 +0300 Subject: [PATCH] Experimental API to toggle tile cache in map view (#2590) --- include/mbgl/renderer/renderer.hpp | 1 + platform/android/CHANGELOG.md | 1 + .../src/cpp/android_renderer_frontend.cpp | 4 ++++ .../src/cpp/android_renderer_frontend.hpp | 1 + .../MapLibreAndroid/src/cpp/native_map_view.cpp | 5 +++++ .../MapLibreAndroid/src/cpp/native_map_view.hpp | 2 ++ .../org/maplibre/android/maps/MapLibreMap.java | 14 ++++++++++++++ .../java/org/maplibre/android/maps/NativeMap.java | 2 ++ .../org/maplibre/android/maps/NativeMapView.java | 11 +++++++++++ platform/darwin/src/MLNRendererFrontend.h | 5 +++++ platform/ios/CHANGELOG.md | 2 ++ platform/ios/src/MLNMapView.h | 10 ++++++++++ platform/ios/src/MLNMapView.mm | 6 ++++++ src/mbgl/renderer/render_orchestrator.cpp | 9 +++++++++ src/mbgl/renderer/render_orchestrator.hpp | 2 ++ src/mbgl/renderer/render_source.hpp | 2 ++ src/mbgl/renderer/renderer.cpp | 4 ++++ src/mbgl/renderer/sources/render_tile_source.cpp | 4 ++++ src/mbgl/renderer/sources/render_tile_source.hpp | 1 + src/mbgl/renderer/tile_pyramid.cpp | 8 +++++--- src/mbgl/renderer/tile_pyramid.hpp | 3 ++- 21 files changed, 93 insertions(+), 4 deletions(-) diff --git a/include/mbgl/renderer/renderer.hpp b/include/mbgl/renderer/renderer.hpp index 69c01a56f..fc2a67ef8 100644 --- a/include/mbgl/renderer/renderer.hpp +++ b/include/mbgl/renderer/renderer.hpp @@ -108,6 +108,7 @@ public: const std::vector& getPlacedSymbolsData() const; // Memory + void setTileCacheEnabled(bool); void reduceMemoryUse(); void clearData(); diff --git a/platform/android/CHANGELOG.md b/platform/android/CHANGELOG.md index 3956723f9..1d326b4e1 100644 --- a/platform/android/CHANGELOG.md +++ b/platform/android/CHANGELOG.md @@ -5,6 +5,7 @@ ### ✨ Features and improvements - Avoid logging error for onMove(0,0) on Android ([#2580](https://github.com/maplibre/maplibre-native/pull/2580)). +- Experimental API to toggle tile cache in map view ([#2590](https://github.com/maplibre/maplibre-native/pull/2590)). This can reduce memory usage at the cost of having to parse tile data again when the zoom level changes. ### 🐞 Bug fixes diff --git a/platform/android/MapLibreAndroid/src/cpp/android_renderer_frontend.cpp b/platform/android/MapLibreAndroid/src/cpp/android_renderer_frontend.cpp index db4a5ae69..6b994aa16 100644 --- a/platform/android/MapLibreAndroid/src/cpp/android_renderer_frontend.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/android_renderer_frontend.cpp @@ -86,6 +86,10 @@ const TaggedScheduler& AndroidRendererFrontend::getThreadPool() const { return mapRenderer.getThreadPool(); } +void AndroidRendererFrontend::setTileCacheEnabled(bool enabled) { + mapRenderer.actor().invoke(&Renderer::setTileCacheEnabled, enabled); +} + void AndroidRendererFrontend::reduceMemoryUse() { mapRenderer.actor().invoke(&Renderer::reduceMemoryUse); } diff --git a/platform/android/MapLibreAndroid/src/cpp/android_renderer_frontend.hpp b/platform/android/MapLibreAndroid/src/cpp/android_renderer_frontend.hpp index 383580fb4..85f2c254a 100644 --- a/platform/android/MapLibreAndroid/src/cpp/android_renderer_frontend.hpp +++ b/platform/android/MapLibreAndroid/src/cpp/android_renderer_frontend.hpp @@ -54,6 +54,7 @@ public: const std::optional>& args) const; // Memory + void setTileCacheEnabled(bool); void reduceMemoryUse(); private: diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp index 988eb929a..d08f3ac34 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.cpp @@ -676,6 +676,10 @@ jni::Local> NativeMapView::addMarkers(jni::JNIEnv& env, return result; } +void NativeMapView::setTileCacheEnabled(JNIEnv&, jni::jboolean enabled) { + rendererFrontend->setTileCacheEnabled(enabled); +} + void NativeMapView::onLowMemory(JNIEnv&) { rendererFrontend->reduceMemoryUse(); } @@ -1284,6 +1288,7 @@ void NativeMapView::registerNative(jni::JNIEnv& env) { METHOD(&NativeMapView::setDebug, "nativeSetDebug"), METHOD(&NativeMapView::getDebug, "nativeGetDebug"), METHOD(&NativeMapView::isFullyLoaded, "nativeIsFullyLoaded"), + METHOD(&NativeMapView::setTileCacheEnabled, "nativeSetTileCacheEnabled"), METHOD(&NativeMapView::onLowMemory, "nativeOnLowMemory"), METHOD(&NativeMapView::getMetersPerPixelAtLatitude, "nativeGetMetersPerPixelAtLatitude"), METHOD(&NativeMapView::projectedMetersForLatLng, "nativeProjectedMetersForLatLng"), diff --git a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp index 3012b4f5d..7cc293973 100644 --- a/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp +++ b/platform/android/MapLibreAndroid/src/cpp/native_map_view.hpp @@ -192,6 +192,8 @@ public: jni::Local> addMarkers(jni::JNIEnv&, const jni::Array>&); + void setTileCacheEnabled(JNIEnv&, jni::jboolean); + void onLowMemory(JNIEnv& env); void setDebug(JNIEnv&, jni::jboolean); diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java index cc7ca0f9f..55bde01c7 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/MapLibreMap.java @@ -2504,4 +2504,18 @@ public final class MapLibreMap { listener.onDeveloperAnimationStarted(); } } + + // + // Tile cache + // + + /** + * Indicating whether the map may cache tiles for different zoom levels or not. + * + * @param enabled true causes the map view to consume more memory and have a smoother user + * experience when zoom in/out. The default value of this property is `true`. + */ + public void experimental_setTileCacheEnabled(boolean enabled) { + nativeMapView.setTileCacheEnabled(enabled); + } } diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java index bcbacfc2c..25c57de4d 100644 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMap.java @@ -33,6 +33,8 @@ interface NativeMap { void resizeView(int width, int height); + void setTileCacheEnabled(boolean enabled); + void onLowMemory(); void destroy(); diff --git a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java index 16ea97374..4edd87101 100755 --- a/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java +++ b/platform/android/MapLibreAndroid/src/main/java/org/maplibre/android/maps/NativeMapView.java @@ -619,6 +619,14 @@ final class NativeMapView implements NativeMap { nativeSetVisibleCoordinateBounds(coordinates, padding, direction, duration); } + @Override + public void setTileCacheEnabled(boolean enabled) { + if (checkState("setTileCacheEnabled")) { + return; + } + nativeSetTileCacheEnabled(enabled); + } + @Override public void onLowMemory() { if (checkState("onLowMemory")) { @@ -1332,6 +1340,9 @@ final class NativeMapView implements NativeMap { private native void nativeSetVisibleCoordinateBounds(LatLng[] coordinates, RectF padding, double direction, long duration); + @Keep + private native void nativeSetTileCacheEnabled(boolean enabled); + @Keep private native void nativeOnLowMemory(); diff --git a/platform/darwin/src/MLNRendererFrontend.h b/platform/darwin/src/MLNRendererFrontend.h index c631dda7c..9bd58bfab 100644 --- a/platform/darwin/src/MLNRendererFrontend.h +++ b/platform/darwin/src/MLNRendererFrontend.h @@ -58,6 +58,11 @@ class MLNRenderFrontend : public mbgl::RendererFrontend { mbgl::Renderer* getRenderer() { return renderer.get(); } + void setTileCacheEnabled(bool enable) { + if (!renderer) return; + renderer->setTileCacheEnabled(enable); + } + void reduceMemoryUse() { if (!renderer) return; renderer->reduceMemoryUse(); diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md index 9a1bcf80e..3c0dbae6d 100644 --- a/platform/ios/CHANGELOG.md +++ b/platform/ios/CHANGELOG.md @@ -4,6 +4,8 @@ MapLibre welcomes participation and contributions from everyone. Please read [`C ## main +- Experimental API to toggle tile cache in map view ([#2590](https://github.com/maplibre/maplibre-native/pull/2590)). This can reduce memory usage at the cost of having to parse tile data again when the zoom level changes. + ## 6.5.1 - Enable LTO ([#2504](https://github.com/maplibre/maplibre-native/pull/2504)). diff --git a/platform/ios/src/MLNMapView.h b/platform/ios/src/MLNMapView.h index daeba3059..6bbcdd781 100644 --- a/platform/ios/src/MLNMapView.h +++ b/platform/ios/src/MLNMapView.h @@ -2111,6 +2111,16 @@ MLN_EXPORT predicate:(nullable NSPredicate *)predicate NS_SWIFT_NAME(visibleFeatures(in:styleLayerIdentifiers:predicate:)); +// MARK: Tile Cache + +/** + Indicating whether the map may cache tiles for different zoom levels or not. + + @param enabled causes the map view to consume more memory and have a smoother user + * experience when zoom in/out. The default value of this property is `YES`. + */ +- (void)experimental_setTileCacheEnabled:(BOOL)enabled; + // MARK: Debugging the Map /** diff --git a/platform/ios/src/MLNMapView.mm b/platform/ios/src/MLNMapView.mm index aa03e2ebb..c44eebbd8 100644 --- a/platform/ios/src/MLNMapView.mm +++ b/platform/ios/src/MLNMapView.mm @@ -7340,6 +7340,12 @@ static void *windowScreenContext = &windowScreenContext; return _mbglView->getObject(); } +// MARK: Tile Cache + +- (void)experimental_setTileCacheEnabled:(BOOL)enabled { + _rendererFrontend->setTileCacheEnabled(enabled); +} + @end // MARK: - IBAdditions methods diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index ab2bf4d2e..7a6d243fc 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -330,6 +330,7 @@ std::unique_ptr RenderOrchestrator::createRenderTree( for (const auto& entry : sourceDiff.added) { std::unique_ptr renderSource = RenderSource::create(entry.second, threadPool); renderSource->setObserver(this); + renderSource->enableCache(tileCacheEnabled); renderSources.emplace(entry.first, std::move(renderSource)); } transformState = updateParameters->transformState; @@ -737,6 +738,14 @@ void RenderOrchestrator::removeFeatureState(const std::string& sourceID, } } +void RenderOrchestrator::setTileCacheEnabled(bool enable) { + tileCacheEnabled = enable; + + for (const auto& entry : renderSources) { + entry.second->enableCache(enable); + } +} + void RenderOrchestrator::reduceMemoryUse() { MLN_TRACE_FUNC(); diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp index 3ec1fe6dd..d04bc4742 100644 --- a/src/mbgl/renderer/render_orchestrator.hpp +++ b/src/mbgl/renderer/render_orchestrator.hpp @@ -92,6 +92,7 @@ public: const std::optional& featureID, const std::optional& stateKey); + void setTileCacheEnabled(bool); void reduceMemoryUse(); void dumpDebugLogs(); void collectPlacedSymbolData(bool); @@ -206,6 +207,7 @@ private: const bool backgroundLayerAsColor; bool contextLost = false; bool placedSymbolDataCollected = false; + bool tileCacheEnabled = true; // Vectors with reserved capacity of layerImpls->size() to avoid // reallocation on each frame. diff --git a/src/mbgl/renderer/render_source.hpp b/src/mbgl/renderer/render_source.hpp index d113f2274..f9925d491 100644 --- a/src/mbgl/renderer/render_source.hpp +++ b/src/mbgl/renderer/render_source.hpp @@ -101,6 +101,8 @@ public: const std::optional&, const std::optional&) {} + virtual void enableCache(bool) {}; + virtual void reduceMemoryUse() = 0; virtual void dumpDebugLogs() const = 0; diff --git a/src/mbgl/renderer/renderer.cpp b/src/mbgl/renderer/renderer.cpp index 53a6072f1..bcf162274 100644 --- a/src/mbgl/renderer/renderer.cpp +++ b/src/mbgl/renderer/renderer.cpp @@ -134,6 +134,10 @@ const std::vector& Renderer::getPlacedSymbolsData() const { return impl->orchestrator.getPlacedSymbolsData(); } +void Renderer::setTileCacheEnabled(bool enable) { + impl->orchestrator.setTileCacheEnabled(enable); +} + void Renderer::reduceMemoryUse() { gfx::BackendScope guard{impl->backend}; impl->reduceMemoryUse(); diff --git a/src/mbgl/renderer/sources/render_tile_source.cpp b/src/mbgl/renderer/sources/render_tile_source.cpp index efc9787e2..bbdbe464a 100644 --- a/src/mbgl/renderer/sources/render_tile_source.cpp +++ b/src/mbgl/renderer/sources/render_tile_source.cpp @@ -494,6 +494,10 @@ void RenderTileSource::removeFeatureState(const std::optional& sour featureState.removeState(sourceLayerID, featureID, stateKey); } +void RenderTileSource::enableCache(bool enable) { + tilePyramid.enableCache(enable); +} + void RenderTileSource::reduceMemoryUse() { tilePyramid.reduceMemoryUse(); } diff --git a/src/mbgl/renderer/sources/render_tile_source.hpp b/src/mbgl/renderer/sources/render_tile_source.hpp index a755bdd41..5ad78e11c 100644 --- a/src/mbgl/renderer/sources/render_tile_source.hpp +++ b/src/mbgl/renderer/sources/render_tile_source.hpp @@ -47,6 +47,7 @@ public: const std::optional&, const std::optional&) override; + void enableCache(bool) override; void reduceMemoryUse() override; void dumpDebugLogs() const override; diff --git a/src/mbgl/renderer/tile_pyramid.cpp b/src/mbgl/renderer/tile_pyramid.cpp index 82753ccc4..f3f6e5091 100644 --- a/src/mbgl/renderer/tile_pyramid.cpp +++ b/src/mbgl/renderer/tile_pyramid.cpp @@ -215,12 +215,14 @@ void TilePyramid::update(const std::vector>& l } } - if (type != SourceType::Annotations) { + if (type != SourceType::Annotations && cacheEnabled) { auto conservativeCacheSize = static_cast( std::max(static_cast(parameters.transformState.getSize().width) / tileSize, 1.0) * std::max(static_cast(parameters.transformState.getSize().height) / tileSize, 1.0) * (parameters.transformState.getMaxZoom() - parameters.transformState.getMinZoom() + 1) * 0.5); cache.setSize(conservativeCacheSize); + } else { + cache.setSize(0); } // Remove stale tiles. This goes through the (sorted!) tiles map and retain @@ -388,8 +390,8 @@ std::vector TilePyramid::querySourceFeatures(const SourceQueryOptions& return result; } -void TilePyramid::setCacheSize(size_t size) { - cache.setSize(size); +void TilePyramid::enableCache(bool enable) { + cacheEnabled = enable; } void TilePyramid::reduceMemoryUse() { diff --git a/src/mbgl/renderer/tile_pyramid.hpp b/src/mbgl/renderer/tile_pyramid.hpp index 5068093ff..c56d7ea23 100644 --- a/src/mbgl/renderer/tile_pyramid.hpp +++ b/src/mbgl/renderer/tile_pyramid.hpp @@ -60,7 +60,7 @@ public: std::vector querySourceFeatures(const SourceQueryOptions&) const; - void setCacheSize(size_t); + void enableCache(bool); void reduceMemoryUse(); void setObserver(TileObserver*); @@ -84,6 +84,7 @@ private: float prevLng = 0; bool fadingTiles = false; + bool cacheEnabled = true; }; } // namespace mbgl