diff --git a/.gitignore b/.gitignore index d8959d4f3..833025085 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ /test/build /test/node_modules /test/fixtures/*/*_actual.* +/test/fixtures/database/*.db /include/mbgl/shader/shaders.hpp /src/shader/shaders_gl.cpp /src/shader/shaders_gles2.cpp diff --git a/android/cpp/jni.cpp b/android/cpp/jni.cpp index ac5188484..2c7e75778 100644 --- a/android/cpp/jni.cpp +++ b/android/cpp/jni.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -255,20 +256,6 @@ void JNICALL nativeDestroySurface(JNIEnv *env, jobject obj, jlong nativeMapViewP nativeMapView->destroySurface(); } -void JNICALL nativeStart(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeStart"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - nativeMapView->start(); -} - -void JNICALL nativeStop(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeStop"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - nativeMapView->stop(); -} - void JNICALL nativePause(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativePause"); assert(nativeMapViewPtr != 0); @@ -287,14 +274,7 @@ void JNICALL nativeUpdate(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdate"); assert(nativeMapViewPtr != 0); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - nativeMapView->getMap().triggerUpdate(); -} - -void JNICALL nativeTerminate(JNIEnv *env, jobject obj, jlong nativeMapViewPtr) { - mbgl::Log::Debug(mbgl::Event::JNI, "nativeTerminate"); - assert(nativeMapViewPtr != 0); - NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - nativeMapView->getMap().terminate(); + nativeMapView->getMap().update(); } void JNICALL nativeResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint width, jint height, @@ -310,7 +290,7 @@ void JNICALL nativeResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint assert(fbWidth <= UINT16_MAX); assert(fbHeight <= UINT16_MAX); NativeMapView *nativeMapView = reinterpret_cast(nativeMapViewPtr); - nativeMapView->resize(width, height, ratio, fbWidth, fbHeight); + nativeMapView->getMap().resize(width, height, ratio); } void JNICALL nativeRemoveClass(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring clazz) { @@ -938,12 +918,9 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) { {"nativeCreateSurface", "(JLandroid/view/Surface;)V", reinterpret_cast(&nativeCreateSurface)}, {"nativeDestroySurface", "(J)V", reinterpret_cast(&nativeDestroySurface)}, - {"nativeStart", "(J)V", reinterpret_cast(&nativeStart)}, - {"nativeStop", "(J)V", reinterpret_cast(&nativeStop)}, {"nativePause", "(J)V", reinterpret_cast(&nativePause)}, {"nativeResume", "(J)V", reinterpret_cast(&nativeResume)}, {"nativeUpdate", "(J)V", reinterpret_cast(&nativeUpdate)}, - {"nativeTerminate", "(J)V", reinterpret_cast(&nativeTerminate)}, {"nativeResize", "(JIIFII)V", reinterpret_cast(static_cast(&nativeResize))}, diff --git a/android/cpp/native_map_view.cpp b/android/cpp/native_map_view.cpp index 39a777bff..5f6b078a7 100644 --- a/android/cpp/native_map_view.cpp +++ b/android/cpp/native_map_view.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -16,6 +17,7 @@ #include #include +#include pthread_once_t loadGLExtensions = PTHREAD_ONCE_INIT; @@ -59,7 +61,7 @@ NativeMapView::NativeMapView(JNIEnv *env, jobject obj_) : mbgl::View(*this), fileCache(mbgl::android::cachePath + "/mbgl-cache.db"), fileSource(&fileCache), - map(*this, fileSource) { + map(*this, fileSource, MapMode::Continuous, true) { mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::NativeMapView"); assert(env != nullptr); @@ -121,11 +123,11 @@ void NativeMapView::deactivate() { } } -void NativeMapView::invalidate() { +void NativeMapView::invalidate(std::function render) { mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::invalidate"); if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE)) { - map.render(); + render(); if (!eglSwapBuffers(display, surface)) { mbgl::Log::Error(mbgl::Event::OpenGL, "eglSwapBuffers() returned error %d", @@ -576,23 +578,6 @@ EGLConfig NativeMapView::chooseConfig(const EGLConfig configs[], EGLint numConfi return configId; } -void NativeMapView::start() { - mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::start"); - - if (display == EGL_NO_DISPLAY) { - initializeDisplay(); - } - - if (context == EGL_NO_CONTEXT) { - initializeContext(); - } - - assert(display != EGL_NO_DISPLAY); - assert(context != EGL_NO_CONTEXT); - - map.start(true); -} - void loadExtensions() { const GLubyte *str = glGetString(GL_EXTENSIONS); if (str == nullptr) { @@ -689,14 +674,6 @@ void loadExtensions() { } } -void NativeMapView::stop() { - mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::stop"); - - if ((display != EGL_NO_DISPLAY) && (context != EGL_NO_CONTEXT)) { - map.stop(); - } -} - void NativeMapView::pause(bool waitForPause) { mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::pause %s", (waitForPause) ? "true" : "false"); @@ -824,9 +801,5 @@ void NativeMapView::updateFps() { env = nullptr; } -void NativeMapView::resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight) { - View::resize(width, height, ratio, fbWidth, fbHeight); -} - } } diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java index f865f9144..da4b40c4c 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/MapView.java @@ -419,7 +419,6 @@ public class MapView extends SurfaceView { mNativeMapView.initializeDisplay(); mNativeMapView.initializeContext(); - mNativeMapView.start(); } // Called when we need to save instance state @@ -441,7 +440,6 @@ public class MapView extends SurfaceView { // Called when we need to clean up // Must be called from Activity onDestroy public void onDestroy() { - mNativeMapView.stop(); mNativeMapView.terminateContext(); mNativeMapView.terminateDisplay(); } diff --git a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java index 4dcd5ef8e..7f074c6db 100644 --- a/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java +++ b/android/java/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxgl/views/NativeMapView.java @@ -73,14 +73,6 @@ class NativeMapView { nativeDestroySurface(mNativeMapViewPtr); } - public void start() { - nativeStart(mNativeMapViewPtr); - } - - public void stop() { - nativeStop(mNativeMapViewPtr); - } - public void pause() { nativePause(mNativeMapViewPtr); } @@ -386,18 +378,12 @@ class NativeMapView { private native void nativeDestroySurface(long nativeMapViewPtr); - private native void nativeStart(long nativeMapViewPtr); - - private native void nativeStop(long nativeMapViewPtr); - private native void nativePause(long nativeMapViewPtr); private native void nativeResume(long nativeMapViewPtr); private native void nativeUpdate(long nativeMapViewPtr); - private native void nativeTerminate(long nativeMapViewPtr); - private native void nativeResize(long nativeMapViewPtr, int width, int height, float ratio, int fbWidth, int fbHeight); diff --git a/include/mbgl/android/native_map_view.hpp b/include/mbgl/android/native_map_view.hpp index 14ccaba3f..a050ad149 100644 --- a/include/mbgl/android/native_map_view.hpp +++ b/include/mbgl/android/native_map_view.hpp @@ -23,7 +23,7 @@ public: void activate() override; void deactivate() override; void notify() override; - void invalidate() override; + void invalidate(std::function render) override; void notifyMapChange(mbgl::MapChange change, Duration delay = Duration::zero()) override; @@ -39,17 +39,12 @@ public: void createSurface(ANativeWindow *window); void destroySurface(); - void start(); - void stop(); - void resume(); void pause(bool waitForPause = false); void enableFps(bool enable); void updateFps(); - void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight); - private: EGLConfig chooseConfig(const EGLConfig configs[], EGLint numConfigs); diff --git a/include/mbgl/map/environment.hpp b/include/mbgl/map/environment.hpp index a00fb2445..07554a7a9 100644 --- a/include/mbgl/map/environment.hpp +++ b/include/mbgl/map/environment.hpp @@ -62,9 +62,6 @@ private: std::vector abandonedVAOs; std::vector abandonedBuffers; std::vector abandonedTextures; - -public: - uv_loop_t* const loop; }; class EnvironmentScope final { diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index f9738debe..a15da5178 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -1,96 +1,57 @@ #ifndef MBGL_MAP_MAP #define MBGL_MAP_MAP -#include #include #include +#include #include -#include #include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include - -namespace uv { class async; } +#include +#include namespace mbgl { -class Painter; -class GlyphStore; -class LayerDescription; -class Sprite; -class Style; -class StyleLayer; -class TexturePool; class FileSource; class View; -class GlyphAtlas; -class SpriteAtlas; -class LineAtlas; -class Environment; -class EnvironmentScope; -class AnnotationManager; class MapData; -class Worker; +class MapContext; class StillImage; +namespace util { +template class Thread; +} + class Map : private util::noncopyable { friend class View; public: - enum class Mode : uint8_t { - None, // we're not doing any processing - Continuous, // continually updating map - Still, // a once-off still image. - }; - - explicit Map(View&, FileSource&); + explicit Map(View&, FileSource&, + MapMode mode = MapMode::Continuous, + bool startPaused = false); ~Map(); - // Start the map render thread. It is asynchronous. - void start(bool startPaused = false, Mode mode = Mode::Continuous); - inline void start(Mode renderMode) { start(false, renderMode); } - - // Stop the map render thread. This call will block until the map rendering thread stopped. - // The optional callback function will be invoked repeatedly until the map thread is stopped. - // The callback function should wait until it is woken up again by view.notify(), otherwise - // this will be a busy waiting loop. - void stop(std::function callback = std::function()); - // Pauses the render thread. The render thread will stop running but will not be terminated and will not lose state until resumed. void pause(bool waitForPause = false); // Resumes a paused render thread void resume(); + // Register a callback that will get called (on the render thread) when all resources have + // been loaded and a complete render occurs. using StillImageCallback = std::function)>; void renderStill(StillImageCallback callback); // Triggers a synchronous or asynchronous render. void renderSync(); - - // Unconditionally performs a render with the current map state. May only be called from the Map - // thread. - void render(); + void renderAsync(); // Notifies the Map thread that the state has changed and an update might be necessary. - void triggerUpdate(Update = Update::Nothing); - - // Triggers a render. Can be called from any thread. - void triggerRender(); - - // Releases resources immediately - void terminate(); + void update(Update update = Update::Nothing); // Styling void addClass(const std::string&); @@ -134,18 +95,23 @@ public: double getBearing() const; void resetNorth(); + // Size + void resize(uint16_t width, uint16_t height, float ratio = 1); + uint16_t getWidth() const; + uint16_t getHeight() const; + // API void setAccessToken(const std::string &token); std::string getAccessToken() const; // Projection - inline void getWorldBoundsMeters(ProjectedMeters &sw, ProjectedMeters &ne) const { Projection::getWorldBoundsMeters(sw, ne); } - inline void getWorldBoundsLatLng(LatLng &sw, LatLng &ne) const { Projection::getWorldBoundsLatLng(sw, ne); } - inline double getMetersPerPixelAtLatitude(const double lat, const double zoom) const { return Projection::getMetersPerPixelAtLatitude(lat, zoom); } - inline const ProjectedMeters projectedMetersForLatLng(const LatLng latLng) const { return Projection::projectedMetersForLatLng(latLng); } - inline const LatLng latLngForProjectedMeters(const ProjectedMeters projectedMeters) const { return Projection::latLngForProjectedMeters(projectedMeters); } - inline const vec2 pixelForLatLng(const LatLng latLng) const { return state.pixelForLatLng(latLng); } - inline const LatLng latLngForPixel(const vec2 pixel) const { return state.latLngForPixel(pixel); } + void getWorldBoundsMeters(ProjectedMeters &sw, ProjectedMeters &ne) const; + void getWorldBoundsLatLng(LatLng &sw, LatLng &ne) const; + double getMetersPerPixelAtLatitude(const double lat, const double zoom) const; + const ProjectedMeters projectedMetersForLatLng(const LatLng latLng) const; + const LatLng latLngForProjectedMeters(const ProjectedMeters projectedMeters) const; + const vec2 pixelForLatLng(const LatLng latLng) const; + const LatLng latLngForPixel(const vec2 pixel) const; // Annotations void setDefaultPointAnnotationSymbol(const std::string&); @@ -160,7 +126,6 @@ public: // Memory void setSourceTileCacheSize(size_t); - size_t getSourceTileCacheSize() const { return sourceCacheSize; } void onLowMemory(); // Debug @@ -168,104 +133,9 @@ public: void toggleDebug(); bool getDebug() const; - inline const TransformState &getState() const { return state; } - TimePoint getTime() const; - inline AnnotationManager& getAnnotationManager() const { return *annotationManager; } - private: - // Runs the map event loop. ONLY run this function when you want to get render a single frame - // with this map object. It will *not* spawn a separate thread and instead block until the - // frame is completely rendered. - void run(); - - // This may only be called by the View object. - void resize(uint16_t width, uint16_t height, float ratio = 1); - void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight); - - util::ptr getSprite(); - Worker& getWorker(); - - // Checks if render thread needs to pause - void checkForPause(); - - // Setup - void setup(); - - void updateTiles(); - - // Triggered by triggerUpdate(); - void update(); - - // Loads the style set in the data object. Called by Update::StyleInfo - void reloadStyle(); - void loadStyleJSON(const std::string& json, const std::string& base); - - // Prepares a map render by updating the tiles we need for the current view, as well as updating - // the stylesheet. - void prepare(); - - // Runs the function in the map thread. - void invokeTask(std::function&&); - template auto invokeSyncTask(const Fn& fn) -> decltype(fn()); - - void processTasks(); - - void updateAnnotationTiles(const std::vector&); - - size_t sourceCacheSize; - - Mode mode = Mode::None; - - const std::unique_ptr env; - std::unique_ptr scope; - View &view; - -private: - std::unique_ptr workers; - std::thread thread; - std::unique_ptr asyncTerminate; - std::unique_ptr asyncUpdate; - std::unique_ptr asyncInvoke; - std::unique_ptr asyncRender; - - bool terminating = false; - bool pausing = false; - bool isPaused = false; - std::mutex mutexRun; - std::condition_variable condRun; - std::mutex mutexPause; - std::condition_variable condPause; - - // Used to signal that rendering completed. - bool rendered = false; - std::condition_variable condRendered; - std::mutex mutexRendered; - - // Stores whether the map thread has been stopped already. - std::atomic_bool isStopped; - - Transform transform; - TransformState state; - - FileSource& fileSource; - - util::ptr