summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2015-09-01 15:07:17 +0300
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-04-14 13:44:08 -0700
commit204c7fee032bf8509747046b43a788366a189ae7 (patch)
tree8719b7ab8838bea52babd8bf42f2234ddc43dc9a
parent18d8e80f52345a13236ae1da99b5866e7643f85b (diff)
downloadqtlocation-mapboxgl-204c7fee032bf8509747046b43a788366a189ae7.tar.gz
[core] Render from the main thread
Do not create a thread for the MapContext anymore.
-rw-r--r--include/mbgl/map/map.hpp19
-rw-r--r--include/mbgl/map/view.hpp52
-rw-r--r--include/mbgl/platform/default/glfw_view.hpp5
-rw-r--r--include/mbgl/platform/default/headless_view.hpp19
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java10
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java24
-rwxr-xr-xplatform/android/src/jni.cpp32
-rwxr-xr-xplatform/android/src/native_map_view.cpp43
-rwxr-xr-xplatform/android/src/native_map_view.hpp6
-rw-r--r--platform/darwin/src/headless_view_cgl.cpp2
-rw-r--r--platform/darwin/src/headless_view_eagl.mm2
-rw-r--r--platform/default/glfw_view.cpp33
-rw-r--r--platform/default/headless_view.cpp52
-rw-r--r--platform/default/headless_view_glx.cpp2
-rw-r--r--platform/ios/src/MGLMapView.mm53
-rw-r--r--platform/node/src/node_map.cpp20
-rw-r--r--platform/node/src/node_mapbox_gl_native.cpp15
-rw-r--r--platform/node/src/node_mapbox_gl_native.hpp9
-rw-r--r--platform/node/test/js/map.test.js4
-rw-r--r--platform/osx/src/MGLMapView.mm103
-rw-r--r--src/mbgl/map/map.cpp82
-rw-r--r--src/mbgl/map/map_context.cpp33
-rw-r--r--src/mbgl/map/map_context.hpp3
-rw-r--r--src/mbgl/map/map_data.hpp17
-rw-r--r--src/mbgl/util/thread_context.hpp2
-rw-r--r--test/api/annotations.cpp25
-rw-r--r--test/api/api_misuse.cpp16
-rw-r--r--test/api/custom_layer.cpp3
-rw-r--r--test/api/render_missing.cpp11
-rw-r--r--test/api/repeated_render.cpp27
-rw-r--r--test/api/set_style.cpp3
-rw-r--r--test/map/map.cpp48
-rw-r--r--test/src/mbgl/test/mock_view.hpp3
-rw-r--r--test/src/mbgl/test/util.cpp14
-rw-r--r--test/test.gypi1
35 files changed, 268 insertions, 525 deletions
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index 9d586d8b8a..b70c388183 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -32,10 +32,6 @@ class ShapeAnnotation;
struct CameraOptions;
struct AnimationOptions;
-namespace util {
-template <class T> class Thread;
-} // namespace util
-
class Map : private util::noncopyable {
friend class View;
@@ -46,22 +42,15 @@ public:
ConstrainMode constrainMode = ConstrainMode::HeightOnly);
~Map();
- // 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 isPaused();
-
- // 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 (std::exception_ptr, PremultipliedImage&&)>;
void renderStill(StillImageCallback callback);
- // Triggers a synchronous render.
- void renderSync();
+ // Main render function.
+ void render();
- // Notifies the Map thread that the state has changed and an update might be necessary.
+ // Notifies the Map that the state has changed and an update might be necessary.
void update(Update update);
// Styling
@@ -189,7 +178,7 @@ public:
private:
View& view;
const std::unique_ptr<Transform> transform;
- const std::unique_ptr<util::Thread<MapContext>> context;
+ const std::unique_ptr<MapContext> context;
MapData* data;
enum class RenderState {
diff --git a/include/mbgl/map/view.hpp b/include/mbgl/map/view.hpp
index 6f481c4458..fd11080064 100644
--- a/include/mbgl/map/view.hpp
+++ b/include/mbgl/map/view.hpp
@@ -30,44 +30,42 @@ enum MapChange : uint8_t {
class View {
public:
- // Called from the main thread directly after initialization. Must always return the same value,
- // i.e. it may not change over time.
+ virtual ~View() = default;
+
+ // Called directly after initialization. Must always return the same value, i.e. it may
+ // not change over time.
virtual float getPixelRatio() const = 0;
- // Called from the main thread when the View signaled a dimension change. Must return the
- // logical dimension of this map in pixels.
+ // Called when the View signaled a dimension change. Must return the logical dimension
+ // of this map in pixels.
virtual std::array<uint16_t, 2> getSize() const = 0;
- // Called from the main thread for every frame that is being rendered. Must return the absolute
- // dimensions of the current framebuffer. Typically, this is the logical width scaled by the
- // pixel ratio, but in case the view was moved to display with a different pixel ratio, it can
- // also be different from that rule.
+ // Called for every frame that is being rendered. Must return the absolute dimensions of
+ // the current framebuffer. Typically, this is the logical width scaled by the pixel ratio,
+ // but in case the view was moved to display with a different pixel ratio, it can also be
+ // different from that rule.
virtual std::array<uint16_t, 2> getFramebufferSize() const = 0;
- // Called from the main thread when this View is associated with a Map object.
- virtual void initialize(Map *map_);
-
- // Called from the render thread. Makes the GL context active in the current
- // thread. This is typically just called once at the beginning of the
- // renderer setup since the render thread doesn't switch the contexts.
+ // Called when this View is associated with a Map object.
+ virtual void initialize(Map*);
+
+ // Called when the view's GL context needs to be made active or inactive. These are called,
+ // as a matched pair, in four situations:
+ //
+ // 1. When releasing GL resources during Map destruction
+ // 2. When calling a CustomLayerInitializeFunction, during Map::addCustomLayer
+ // 3. When calling a CustomLayerDeinitializeFunction, during Map::removeCustomLayer
+ // 4. When rendering for Map::renderStill
+ //
+ // They are *not* called for Map::render; it is assumed that the correct context is already
+ // activated prior to calling Map::render.
virtual void activate() = 0;
-
- // Called from the render thread. Makes the GL context inactive in the current
- // thread. This is called once just before the rendering thread terminates.
virtual void deactivate() = 0;
- virtual void notify() = 0;
-
- // Called from the render thread. The implementation must trigger a rerender.
- // (map->renderSync() from the main thread must be called as a result of this)
+ // Called when the map needs to be rendered; the view should call Map::render() at some point
+ // in the near future. (Not called for Map::renderStill() mode.)
virtual void invalidate() = 0;
- // Called from the render thread before the render begins.
- virtual void beforeRender() = 0;
-
- // Called from the render thread after the render is complete.
- virtual void afterRender() = 0;
-
// Reads the pixel data from the current framebuffer. If your View implementation
// doesn't support reading from the framebuffer, return a null pointer.
virtual PremultipliedImage readStillImage();
diff --git a/include/mbgl/platform/default/glfw_view.hpp b/include/mbgl/platform/default/glfw_view.hpp
index 802f61b0c0..74a545d31b 100644
--- a/include/mbgl/platform/default/glfw_view.hpp
+++ b/include/mbgl/platform/default/glfw_view.hpp
@@ -22,13 +22,10 @@ public:
std::array<uint16_t, 2> getSize() const override;
std::array<uint16_t, 2> getFramebufferSize() const override;
- void initialize(mbgl::Map *map) override;
+ void initialize(mbgl::Map*) override;
void activate() override;
void deactivate() override;
- void notify() override;
void invalidate() override;
- void beforeRender() override;
- void afterRender() override;
static void onKey(GLFWwindow *window, int key, int scancode, int action, int mods);
static void onScroll(GLFWwindow *window, double xoffset, double yoffset);
diff --git a/include/mbgl/platform/default/headless_view.hpp b/include/mbgl/platform/default/headless_view.hpp
index edaa08d01d..9fbbdfd206 100644
--- a/include/mbgl/platform/default/headless_view.hpp
+++ b/include/mbgl/platform/default/headless_view.hpp
@@ -38,34 +38,31 @@ public:
std::array<uint16_t, 2> getSize() const override;
std::array<uint16_t, 2> getFramebufferSize() const override;
+ void invalidate() override;
void activate() override;
void deactivate() override;
- void notify() override;
- void invalidate() override;
- void beforeRender() override;
- void afterRender() override;
+
PremultipliedImage readStillImage() override;
- void resizeFramebuffer();
void resize(uint16_t width, uint16_t height);
private:
- void loadExtensions();
- bool isActive() const;
-
// Implementation specific functions
static gl::glProc initializeExtension(const char*);
void createContext();
void destroyContext();
void clearBuffers();
+ void resizeFramebuffer();
void activateContext();
void deactivateContext();
-private:
std::shared_ptr<HeadlessDisplay> display;
const float pixelRatio;
std::array<uint16_t, 2> dimensions;
+
bool needsResize = false;
+ bool extensionsLoaded = false;
+ bool active = false;
#if MBGL_USE_CGL
CGLContextObj glContext = nullptr;
@@ -82,13 +79,9 @@ private:
GLXPbuffer glxPbuffer = 0;
#endif
- bool extensionsLoaded = false;
-
GLuint fbo = 0;
GLuint fboDepthStencil = 0;
GLuint fboColor = 0;
-
- std::thread::id thread;
};
} // namespace mbgl
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
index abe0bdc317..963ae8d750 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java
@@ -521,7 +521,6 @@ public class MapView extends FrameLayout {
mConnectivityReceiver = null;
mUserLocationView.onPause();
- mNativeMapView.pause();
}
/**
@@ -533,7 +532,6 @@ public class MapView extends FrameLayout {
mConnectivityReceiver = new ConnectivityReceiver();
getContext().registerReceiver(mConnectivityReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
- mNativeMapView.resume();
mNativeMapView.update();
mUserLocationView.onResume();
@@ -1094,9 +1092,7 @@ public class MapView extends FrameLayout {
}
int getTopOffsetPixelsForIcon(Icon icon) {
- // This method will dead lock if map paused. Causes a freeze if you add a marker in an
- // activity's onCreate()
- if (mDestroyed || mNativeMapView.isPaused()) {
+ if (mDestroyed) {
return 0;
}
@@ -1243,11 +1239,11 @@ public class MapView extends FrameLayout {
return;
}
- if (mDestroyed || mNativeMapView.isPaused()) {
+ if (mDestroyed) {
return;
}
- mNativeMapView.renderSync();
+ mNativeMapView.render();
}
@Override
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
index 6b5a02cf06..bf342bdb40 100755
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java
@@ -119,24 +119,12 @@ final class NativeMapView {
nativeDestroySurface(mNativeMapViewPtr);
}
- public void pause() {
- nativePause(mNativeMapViewPtr);
- }
-
- public boolean isPaused() {
- return nativeIsPaused(mNativeMapViewPtr);
- }
-
- public void resume() {
- nativeResume(mNativeMapViewPtr);
- }
-
public void update() {
nativeUpdate(mNativeMapViewPtr);
}
- public void renderSync() {
- nativeRenderSync(mNativeMapViewPtr);
+ public void render() {
+ nativeRender(mNativeMapViewPtr);
}
public void resizeView(int width, int height) {
@@ -515,15 +503,9 @@ final class NativeMapView {
private native void nativeDestroySurface(long nativeMapViewPtr);
- private native void nativePause(long nativeMapViewPtr);
-
- private native boolean nativeIsPaused(long nativeMapViewPtr);
-
- private native void nativeResume(long nativeMapViewPtr);
-
private native void nativeUpdate(long nativeMapViewPtr);
- private native void nativeRenderSync(long nativeMapViewPtr);
+ private native void nativeRender(long nativeMapViewPtr);
private native void nativeViewResize(long nativeMapViewPtr, int width, int height);
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index 08e5e697ae..e0d5bb65df 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -404,27 +404,6 @@ void nativeDestroySurface(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr
nativeMapView->destroySurface();
}
-void nativePause(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativePause");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->pause();
-}
-
-jboolean nativeIsPaused(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeIsPaused");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- return nativeMapView->getMap().isPaused();
-}
-
-void nativeResume(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeResume");
- assert(nativeMapViewPtr != 0);
- NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->resume();
-}
-
void nativeUpdate(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeUpdate");
assert(nativeMapViewPtr != 0);
@@ -432,11 +411,11 @@ void nativeUpdate(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
nativeMapView->getMap().update(mbgl::Update::Repaint);
}
-void nativeRenderSync(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
- mbgl::Log::Debug(mbgl::Event::JNI, "nativeRenderSync");
+void nativeRender(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr) {
+ mbgl::Log::Debug(mbgl::Event::JNI, "nativeRender");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
- nativeMapView->getMap().renderSync();
+ nativeMapView->render();
}
void nativeViewResize(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jint width, jint height) {
@@ -1815,11 +1794,8 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
MAKE_NATIVE_METHOD(nativeTerminateContext, "(J)V"),
MAKE_NATIVE_METHOD(nativeCreateSurface, "(JLandroid/view/Surface;)V"),
MAKE_NATIVE_METHOD(nativeDestroySurface, "(J)V"),
- MAKE_NATIVE_METHOD(nativePause, "(J)V"),
- MAKE_NATIVE_METHOD(nativeIsPaused, "(J)Z"),
- MAKE_NATIVE_METHOD(nativeResume, "(J)V"),
MAKE_NATIVE_METHOD(nativeUpdate, "(J)V"),
- MAKE_NATIVE_METHOD(nativeRenderSync, "(J)V"),
+ MAKE_NATIVE_METHOD(nativeRender, "(J)V"),
MAKE_NATIVE_METHOD(nativeViewResize, "(JII)V"),
MAKE_NATIVE_METHOD(nativeFramebufferResize, "(JII)V"),
MAKE_NATIVE_METHOD(nativeAddClass, "(JLjava/lang/String;)V"),
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index a645d86d4b..6b1d4ff327 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -90,8 +90,6 @@ NativeMapView::NativeMapView(JNIEnv *env, jobject obj_, float pixelRatio_, int a
size_t cacheSize = zoomFactor * cpuFactor * memoryFactor * sizeFactor * 0.5f;
map->setSourceTileCacheSize(cacheSize);
-
- map->pause();
}
NativeMapView::~NativeMapView() {
@@ -189,20 +187,15 @@ void NativeMapView::invalidate() {
detach_jni_thread(vm, &env, detach);
}
-void NativeMapView::beforeRender() {
- mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::beforeRender()");
+void NativeMapView::render() {
+ activate();
if(sizeChanged){
sizeChanged = false;
glViewport(0, 0, fbWidth, fbHeight);
}
-}
-
-void NativeMapView::afterRender() {
- mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::afterRender()");
- assert(vm != nullptr);
- assert(obj != nullptr);
+ map->render();
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE)) {
if (!eglSwapBuffers(display, surface)) {
@@ -215,11 +208,8 @@ void NativeMapView::afterRender() {
} else {
mbgl::Log::Info(mbgl::Event::Android, "Not swapping as we are not ready");
}
-}
-void NativeMapView::notify() {
- mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::notify()");
- // noop
+ deactivate();
}
mbgl::Map &NativeMapView::getMap() { return *map; }
@@ -444,15 +434,11 @@ void NativeMapView::createSurface(ANativeWindow *window_) {
throw std::runtime_error("eglMakeCurrent() failed");
}
}
-
- resume();
}
void NativeMapView::destroySurface() {
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::destroySurface");
- pause();
-
if (surface != EGL_NO_SURFACE) {
if (!eglDestroySurface(display, surface)) {
mbgl::Log::Error(mbgl::Event::OpenGL, "eglDestroySurface() returned error %d",
@@ -669,27 +655,6 @@ EGLConfig NativeMapView::chooseConfig(const EGLConfig configs[], EGLint numConfi
return configId;
}
-void NativeMapView::pause() {
- mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::pause");
-
- if ((display != EGL_NO_DISPLAY) && (context != EGL_NO_CONTEXT)) {
- map->pause();
- }
-}
-
-void NativeMapView::resume() {
- mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::resume");
-
- assert(display != EGL_NO_DISPLAY);
- assert(context != EGL_NO_CONTEXT);
-
- if (surface != EGL_NO_SURFACE) {
- map->resume();
- } else {
- mbgl::Log::Debug(mbgl::Event::Android, "Not resuming because we are not ready");
- }
-}
-
void NativeMapView::notifyMapChange(mbgl::MapChange change) {
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::notifyMapChange()");
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 5926f781ae..b0142adb17 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -24,10 +24,7 @@ public:
std::array<uint16_t, 2> getFramebufferSize() const override;
void activate() override;
void deactivate() override;
- void notify() override;
void invalidate() override;
- void beforeRender() override;
- void afterRender() override;
void notifyMapChange(mbgl::MapChange) override;
@@ -43,8 +40,7 @@ public:
void createSurface(ANativeWindow *window);
void destroySurface();
- void resume();
- void pause();
+ void render();
void enableFps(bool enable);
void updateFps();
diff --git a/platform/darwin/src/headless_view_cgl.cpp b/platform/darwin/src/headless_view_cgl.cpp
index 9f408fcbe8..a4f809a250 100644
--- a/platform/darwin/src/headless_view_cgl.cpp
+++ b/platform/darwin/src/headless_view_cgl.cpp
@@ -76,7 +76,7 @@ void HeadlessView::resizeFramebuffer() {
}
void HeadlessView::clearBuffers() {
- assert(isActive());
+ assert(active);
MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
diff --git a/platform/darwin/src/headless_view_eagl.mm b/platform/darwin/src/headless_view_eagl.mm
index 26b7922168..a1f335fc6e 100644
--- a/platform/darwin/src/headless_view_eagl.mm
+++ b/platform/darwin/src/headless_view_eagl.mm
@@ -72,7 +72,7 @@ void HeadlessView::resizeFramebuffer() {
}
void HeadlessView::clearBuffers() {
- assert(isActive());
+ assert(active);
MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp
index 6bd5f4e196..768e55ca32 100644
--- a/platform/default/glfw_view.cpp
+++ b/platform/default/glfw_view.cpp
@@ -428,7 +428,18 @@ void GLFWView::run() {
const bool dirty = !clean.test_and_set();
if (dirty) {
const double started = glfwGetTime();
- map->renderSync();
+
+ glfwMakeContextCurrent(window);
+ glViewport(0, 0, fbWidth, fbHeight);
+
+ map->render();
+
+ if (showClipMasks) {
+ renderClipMasks();
+ }
+
+ glfwSwapBuffers(window);
+
report(1000 * (glfwGetTime() - started));
if (benchmark) {
map->update(mbgl::Update::Repaint);
@@ -460,31 +471,11 @@ void GLFWView::deactivate() {
glfwMakeContextCurrent(nullptr);
}
-void GLFWView::notify() {
- glfwPostEmptyEvent();
-}
-
void GLFWView::invalidate() {
clean.clear();
glfwPostEmptyEvent();
}
-void GLFWView::beforeRender() {
- // This is called from the map thread but `width` and `height`
- // can be accessed with no race because the main thread is blocked
- // when we render. This will be more straightforward when we move
- // rendering to the main thread.
- glViewport(0, 0, fbWidth, fbHeight);
-}
-
-void GLFWView::afterRender() {
- if (showClipMasks) {
- renderClipMasks();
- }
-
- glfwSwapBuffers(window);
-}
-
void GLFWView::renderClipMasks() {
// Read the stencil buffer
auto pixels = std::make_unique<uint8_t[]>(fbWidth * fbHeight);
diff --git a/platform/default/headless_view.cpp b/platform/default/headless_view.cpp
index a764eb2e06..13ea78a709 100644
--- a/platform/default/headless_view.cpp
+++ b/platform/default/headless_view.cpp
@@ -31,22 +31,6 @@ HeadlessView::~HeadlessView() {
destroyContext();
}
-
-void HeadlessView::loadExtensions() {
- if (extensionsLoaded) {
- return;
- }
-
- gl::InitializeExtensions(initializeExtension);
-
- extensionsLoaded = true;
-}
-
-
-bool HeadlessView::isActive() const {
- return std::this_thread::get_id() == thread;
-}
-
void HeadlessView::resize(const uint16_t width, const uint16_t height) {
if(dimensions[0] == width &&
dimensions[1] == height) {
@@ -57,7 +41,7 @@ void HeadlessView::resize(const uint16_t width, const uint16_t height) {
}
PremultipliedImage HeadlessView::readStillImage() {
- assert(isActive());
+ assert(active);
const unsigned int w = dimensions[0] * pixelRatio;
const unsigned int h = dimensions[1] * pixelRatio;
@@ -76,9 +60,6 @@ PremultipliedImage HeadlessView::readStillImage() {
return image;
}
-void HeadlessView::notify() {
- // no-op
-}
float HeadlessView::getPixelRatio() const {
return pixelRatio;
@@ -94,10 +75,7 @@ std::array<uint16_t, 2> HeadlessView::getFramebufferSize() const {
}
void HeadlessView::activate() {
- if (thread != std::thread::id()) {
- throw std::runtime_error("OpenGL context was already current");
- }
- thread = std::this_thread::get_id();
+ active = true;
if (!glContext) {
if (!display) {
@@ -107,23 +85,12 @@ void HeadlessView::activate() {
}
activateContext();
- loadExtensions();
-}
-void HeadlessView::deactivate() {
- if (thread == std::thread::id()) {
- throw std::runtime_error("OpenGL context was not current");
+ if (!extensionsLoaded) {
+ gl::InitializeExtensions(initializeExtension);
+ extensionsLoaded = true;
}
- thread = std::thread::id();
-
- deactivateContext();
-}
-
-void HeadlessView::invalidate() {
- // no-op
-}
-void HeadlessView::beforeRender() {
if (needsResize) {
clearBuffers();
resizeFramebuffer();
@@ -131,8 +98,13 @@ void HeadlessView::beforeRender() {
}
}
-void HeadlessView::afterRender() {
- // no-op
+void HeadlessView::deactivate() {
+ deactivateContext();
+ active = false;
+}
+
+void HeadlessView::invalidate() {
+ assert(false);
}
} // namespace mbgl
diff --git a/platform/default/headless_view_glx.cpp b/platform/default/headless_view_glx.cpp
index d7ad9f5e55..3b719ab43a 100644
--- a/platform/default/headless_view_glx.cpp
+++ b/platform/default/headless_view_glx.cpp
@@ -93,7 +93,7 @@ void HeadlessView::resizeFramebuffer() {
}
void HeadlessView::clearBuffers() {
- assert(isActive());
+ assert(active);
MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index c989606674..459d3cf011 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -320,7 +320,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
// start paused if in IB
if (_isTargetingInterfaceBuilder || background) {
self.dormant = YES;
- _mbglMap->pause();
}
// Notify map object when network reachability status changes.
@@ -751,8 +750,7 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
NSUInteger cacheSize = zoomFactor * cpuFactor * memoryFactor * sizeFactor * 0.5;
_mbglMap->setSourceTileCacheSize(cacheSize);
-
- _mbglMap->renderSync();
+ _mbglMap->render();
[self updateUserLocationAnnotationView];
}
@@ -895,7 +893,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
{
[self validateDisplayLink];
self.dormant = YES;
- _mbglMap->pause();
[self.glView deleteDrawable];
}
}
@@ -967,8 +964,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
[self.glSnapshotView addSubview:snapshotTint];
}
- _mbglMap->pause();
-
[self.glView deleteDrawable];
}
}
@@ -988,8 +983,6 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
[self.glSnapshotView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[self.glView bindDrawable];
-
- _mbglMap->resume();
_displayLink.paused = NO;
@@ -3957,12 +3950,10 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
class MBGLView : public mbgl::View
{
- public:
- MBGLView(MGLMapView* nativeView_, const float scaleFactor_)
- : nativeView(nativeView_), scaleFactor(scaleFactor_) {
- }
- virtual ~MBGLView() {}
-
+public:
+ MBGLView(MGLMapView* nativeView_, const float scaleFactor_)
+ : nativeView(nativeView_), scaleFactor(scaleFactor_) {
+ }
float getPixelRatio() const override {
return scaleFactor;
@@ -3970,7 +3961,7 @@ class MBGLView : public mbgl::View
std::array<uint16_t, 2> getSize() const override {
return {{ static_cast<uint16_t>([nativeView bounds].size.width),
- static_cast<uint16_t>([nativeView bounds].size.height) }};
+ static_cast<uint16_t>([nativeView bounds].size.height) }};
}
std::array<uint16_t, 2> getFramebufferSize() const override {
@@ -3978,15 +3969,14 @@ class MBGLView : public mbgl::View
static_cast<uint16_t>([[nativeView glView] drawableHeight]) }};
}
- void notify() override
+ void notifyMapChange(mbgl::MapChange change) override
{
- // no-op
+ [nativeView notifyMapChange:change];
}
- void notifyMapChange(mbgl::MapChange change) override
+ void invalidate() override
{
- assert([[NSThread currentThread] isMainThread]);
- [nativeView notifyMapChange:change];
+ [nativeView setNeedsGLDisplay];
}
void activate() override
@@ -3999,26 +3989,9 @@ class MBGLView : public mbgl::View
[EAGLContext setCurrentContext:nil];
}
- void invalidate() override
- {
- [nativeView performSelectorOnMainThread:@selector(setNeedsGLDisplay)
- withObject:nil
- waitUntilDone:NO];
- }
-
- void beforeRender() override
- {
- // no-op
- }
-
- void afterRender() override
- {
- // no-op
- }
-
- private:
- __weak MGLMapView *nativeView = nullptr;
- const float scaleFactor;
+private:
+ __weak MGLMapView *nativeView = nullptr;
+ const float scaleFactor;
};
@end
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index 953e485fe9..7968e83554 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -1,10 +1,8 @@
#include "node_map.hpp"
#include "node_request.hpp"
-#include "node_mapbox_gl_native.hpp"
#include <mbgl/platform/default/headless_display.hpp>
#include <mbgl/util/exception.hpp>
-#include <mbgl/util/work_request.hpp>
#include <unistd.h>
@@ -474,18 +472,16 @@ NodeMap::~NodeMap() {
if (valid) release();
}
-std::unique_ptr<mbgl::AsyncRequest> NodeMap::request(const mbgl::Resource& resource, Callback cb1) {
- // This function can be called from any thread. Make sure we're executing the
- // JS implementation in the node event loop.
- return NodeRunLoop().invokeWithCallback([this] (mbgl::Resource res, Callback cb2) {
- Nan::HandleScope scope;
+std::unique_ptr<mbgl::AsyncRequest> NodeMap::request(const mbgl::Resource& resource, Callback callback_) {
+ Nan::HandleScope scope;
+
+ auto requestHandle = NodeRequest::Create(resource, callback_)->ToObject();
+ auto callbackHandle = Nan::New<v8::Function>(NodeRequest::Respond, requestHandle);
- auto requestHandle = NodeRequest::Create(res, cb2)->ToObject();
- auto callbackHandle = Nan::New<v8::Function>(NodeRequest::Respond, requestHandle);
+ v8::Local<v8::Value> argv[] = { requestHandle, callbackHandle };
+ Nan::MakeCallback(handle()->GetInternalField(1)->ToObject(), "request", 2, argv);
- v8::Local<v8::Value> argv[] = { requestHandle, callbackHandle };
- Nan::MakeCallback(handle()->GetInternalField(1)->ToObject(), "request", 2, argv);
- }, cb1, resource);
+ return std::make_unique<mbgl::AsyncRequest>();
}
}
diff --git a/platform/node/src/node_mapbox_gl_native.cpp b/platform/node/src/node_mapbox_gl_native.cpp
index 28df6af01c..26c49918be 100644
--- a/platform/node/src/node_mapbox_gl_native.cpp
+++ b/platform/node/src/node_mapbox_gl_native.cpp
@@ -5,25 +5,18 @@
#include <nan.h>
#pragma GCC diagnostic pop
-#include "node_mapbox_gl_native.hpp"
+#include <mbgl/util/run_loop.hpp>
+
#include "node_map.hpp"
#include "node_log.hpp"
#include "node_request.hpp"
-namespace node_mbgl {
-
-mbgl::util::RunLoop& NodeRunLoop() {
- static mbgl::util::RunLoop nodeRunLoop;
- return nodeRunLoop;
-}
-
-}
-
void RegisterModule(v8::Local<v8::Object> target, v8::Local<v8::Object> module) {
// This has the effect of:
// a) Ensuring that the static local variable is initialized before any thread contention.
// b) unreffing an async handle, which otherwise would keep the default loop running.
- node_mbgl::NodeRunLoop().stop();
+ static mbgl::util::RunLoop nodeRunLoop;
+ nodeRunLoop.stop();
node_mbgl::NodeMap::Init(target);
node_mbgl::NodeRequest::Init(target);
diff --git a/platform/node/src/node_mapbox_gl_native.hpp b/platform/node/src/node_mapbox_gl_native.hpp
deleted file mode 100644
index b98b035fea..0000000000
--- a/platform/node/src/node_mapbox_gl_native.hpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-
-#include <mbgl/util/run_loop.hpp>
-
-namespace node_mbgl {
-
-mbgl::util::RunLoop& NodeRunLoop();
-
-}
diff --git a/platform/node/test/js/map.test.js b/platform/node/test/js/map.test.js
index 1228900940..12b17126f9 100644
--- a/platform/node/test/js/map.test.js
+++ b/platform/node/test/js/map.test.js
@@ -298,7 +298,9 @@ test('Map', function(t) {
t.test('returning an error', function(t) {
var map = new mbgl.Map({
request: function(req, callback) {
- callback(new Error('request error'));
+ setImmediate(function () {
+ callback(new Error('request error'));
+ });
},
});
map.load(style);
diff --git a/platform/osx/src/MGLMapView.mm b/platform/osx/src/MGLMapView.mm
index 6f20e957a6..5978251437 100644
--- a/platform/osx/src/MGLMapView.mm
+++ b/platform/osx/src/MGLMapView.mm
@@ -540,7 +540,6 @@ public:
[self deselectAnnotation:self.selectedAnnotation];
if (!self.dormant && !newWindow) {
self.dormant = YES;
- _mbglMap->pause();
}
[self.window removeObserver:self forKeyPath:@"contentLayoutRect"];
@@ -550,7 +549,6 @@ public:
- (void)viewDidMoveToWindow {
NSWindow *window = self.window;
if (self.dormant && window) {
- _mbglMap->resume();
self.dormant = NO;
}
@@ -686,8 +684,31 @@ public:
NSUInteger cacheSize = zoomFactor * cpuFactor * memoryFactor * sizeFactor * 0.5;
_mbglMap->setSourceTileCacheSize(cacheSize);
- _mbglMap->renderSync();
-
+
+ // Enable vertex buffer objects.
+ mbgl::gl::InitializeExtensions([](const char *name) {
+ static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+ if (!framework) {
+ throw std::runtime_error("Failed to load OpenGL framework.");
+ }
+
+ CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
+ void *symbol = CFBundleGetFunctionPointerForName(framework, str);
+ CFRelease(str);
+
+ return reinterpret_cast<mbgl::gl::glProc>(symbol);
+ });
+
+ _mbglMap->render();
+
+ if (_isPrinting) {
+ _isPrinting = NO;
+ std::string png = encodePNG(_mbglView->readStillImage());
+ NSData *data = [[NSData alloc] initWithBytes:png.data() length:png.size()];
+ NSImage *image = [[NSImage alloc] initWithData:data];
+ [self printWithImage:image];
+ }
+
// [self updateUserLocationAnnotationView];
}
}
@@ -2270,85 +2291,39 @@ class MGLMapViewImpl : public mbgl::View {
public:
MGLMapViewImpl(MGLMapView *nativeView_, const float scaleFactor_)
: nativeView(nativeView_), scaleFactor(scaleFactor_) {}
- virtual ~MGLMapViewImpl() {}
-
-
+
float getPixelRatio() const override {
return scaleFactor;
}
-
+
std::array<uint16_t, 2> getSize() const override {
return {{ static_cast<uint16_t>(nativeView.bounds.size.width),
- static_cast<uint16_t>(nativeView.bounds.size.height) }};
+ static_cast<uint16_t>(nativeView.bounds.size.height) }};
}
-
+
std::array<uint16_t, 2> getFramebufferSize() const override {
NSRect bounds = [nativeView convertRectToBacking:nativeView.bounds];
return {{ static_cast<uint16_t>(bounds.size.width),
- static_cast<uint16_t>(bounds.size.height) }};
+ static_cast<uint16_t>(bounds.size.height) }};
}
-
- void notify() override {}
-
+
void notifyMapChange(mbgl::MapChange change) override {
- assert([[NSThread currentThread] isMainThread]);
[nativeView notifyMapChange:change];
}
-
+
+ void invalidate() override {
+ [nativeView invalidate];
+ }
+
void activate() override {
MGLOpenGLLayer *layer = (MGLOpenGLLayer *)nativeView.layer;
- if ([NSOpenGLContext currentContext] != layer.openGLContext) {
- // Enable our OpenGL context on the Map thread.
- [layer.openGLContext makeCurrentContext];
-
- // Enable vertex buffer objects.
- mbgl::gl::InitializeExtensions([](const char *name) {
- static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
- if (!framework) {
- throw std::runtime_error("Failed to load OpenGL framework.");
- }
-
- CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
- void *symbol = CFBundleGetFunctionPointerForName(framework, str);
- CFRelease(str);
-
- return reinterpret_cast<mbgl::gl::glProc>(symbol);
- });
- }
+ [layer.openGLContext makeCurrentContext];
}
-
+
void deactivate() override {
[NSOpenGLContext clearCurrentContext];
}
-
- void invalidate() override {
- [nativeView performSelectorOnMainThread:@selector(invalidate)
- withObject:nil
- waitUntilDone:NO];
- }
-
- void beforeRender() override {
- // This normally gets called right away by mbgl::Map, but only on the
- // main thread. OpenGL contexts and extensions are thread-local, so this
- // has to happen on the Map thread too.
- activate();
-
-// auto size = getFramebufferSize();
-// MBGL_CHECK_ERROR(glViewport(0, 0, size[0], size[1]));
- }
-
- void afterRender() override {
- if (nativeView->_isPrinting) {
- nativeView->_isPrinting = NO;
- std::string png = encodePNG(readStillImage());
- NSData *data = [[NSData alloc] initWithBytes:png.data() length:png.size()];
- NSImage *image = [[NSImage alloc] initWithData:data];
- [nativeView performSelectorOnMainThread:@selector(printWithImage:)
- withObject:image
- waitUntilDone:NO];
- }
- }
-
+
mbgl::PremultipliedImage readStillImage() override {
auto size = getFramebufferSize();
const unsigned int w = size[0];
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index c9123495cd..7300e5c3bb 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -12,7 +12,6 @@
#include <mbgl/layer/custom_layer.hpp>
#include <mbgl/util/projection.hpp>
-#include <mbgl/util/thread.hpp>
#include <mbgl/util/math.hpp>
namespace mbgl {
@@ -20,46 +19,24 @@ namespace mbgl {
Map::Map(View& view_, FileSource& fileSource, MapMode mapMode, GLContextMode contextMode, ConstrainMode constrainMode)
: view(view_),
transform(std::make_unique<Transform>(view, constrainMode)),
- context(std::make_unique<util::Thread<MapContext>>(
- util::ThreadContext{"Map", util::ThreadType::Map, util::ThreadPriority::Regular},
+ context(std::make_unique<MapContext>(
view, fileSource, mapMode, contextMode, view.getPixelRatio())),
- data(&context->invokeSync<MapData&>(&MapContext::getData))
+ data(&context->getData())
{
view.initialize(this);
update(Update::Dimensions);
}
Map::~Map() {
- resume();
- context->invokeSync(&MapContext::cleanup);
-}
-
-void Map::pause() {
- assert(data->mode == MapMode::Continuous);
-
- std::unique_lock<std::mutex> lockPause(data->mutexPause);
- if (!data->paused) {
- context->invoke(&MapContext::pause);
- data->condPause.wait(lockPause, [&]{ return data->paused; });
- }
-}
-
-bool Map::isPaused() {
- return data->paused;
-}
-
-void Map::resume() {
- std::unique_lock<std::mutex> lockPause(data->mutexPause);
- data->paused = false;
- data->condPause.notify_all();
+ context->cleanup();
}
void Map::renderStill(StillImageCallback callback) {
- context->invoke(&MapContext::renderStill, transform->getState(),
+ context->renderStill(transform->getState(),
FrameData { view.getFramebufferSize(), Clock::now() }, callback);
}
-void Map::renderSync() {
+void Map::render() {
if (renderState == RenderState::never) {
view.notifyMapChange(MapChangeWillStartRenderingMap);
}
@@ -67,8 +44,7 @@ void Map::renderSync() {
view.notifyMapChange(MapChangeWillStartRenderingFrame);
const Update flags = transform->updateTransitions(Clock::now());
- const bool fullyLoaded = context->invokeSync<bool>(
- &MapContext::renderSync, transform->getState(), FrameData { view.getFramebufferSize(), Clock::now() });
+ const bool fullyLoaded = context->renderSync(transform->getState(), FrameData { view.getFramebufferSize(), Clock::now() });
view.notifyMapChange(fullyLoaded ?
MapChangeDidFinishRenderingFrameFullyRendered :
@@ -94,7 +70,7 @@ void Map::renderSync() {
void Map::update(Update flags) {
if (flags & Update::Dimensions) transform->resize(view.getSize());
- context->invoke(&MapContext::triggerUpdate, transform->getState(), flags);
+ context->triggerUpdate(transform->getState(), flags);
}
#pragma mark - Style
@@ -102,21 +78,21 @@ void Map::update(Update flags) {
void Map::setStyleURL(const std::string &url) {
loading = true;
view.notifyMapChange(MapChangeWillStartLoadingMap);
- context->invoke(&MapContext::setStyleURL, url);
+ context->setStyleURL(url);
}
void Map::setStyleJSON(const std::string& json, const std::string& base) {
loading = true;
view.notifyMapChange(MapChangeWillStartLoadingMap);
- context->invoke(&MapContext::setStyleJSON, json, base);
+ context->setStyleJSON(json, base);
}
std::string Map::getStyleURL() const {
- return context->invokeSync<std::string>(&MapContext::getStyleURL);
+ return context->getStyleURL();
}
std::string Map::getStyleJSON() const {
- return context->invokeSync<std::string>(&MapContext::getStyleJSON);
+ return context->getStyleJSON();
}
#pragma mark - Transitions
@@ -436,15 +412,15 @@ LatLng Map::latLngForPixel(const ScreenCoordinate& pixel) const {
#pragma mark - Annotations
void Map::addAnnotationIcon(const std::string& name, std::shared_ptr<const SpriteImage> sprite) {
- context->invoke(&MapContext::addAnnotationIcon, name, sprite);
+ context->addAnnotationIcon(name, sprite);
}
void Map::removeAnnotationIcon(const std::string& name) {
- context->invoke(&MapContext::removeAnnotationIcon, name);
+ context->removeAnnotationIcon(name);
}
double Map::getTopOffsetPixelsForAnnotationIcon(const std::string& symbol) {
- return context->invokeSync<double>(&MapContext::getTopOffsetPixelsForAnnotationIcon, symbol);
+ return context->getTopOffsetPixelsForAnnotationIcon(symbol);
}
AnnotationID Map::addPointAnnotation(const PointAnnotation& annotation) {
@@ -489,17 +465,21 @@ AnnotationIDs Map::getPointAnnotationsInBounds(const LatLngBounds& bounds) {
void Map::addCustomLayer(const std::string& id,
CustomLayerInitializeFunction initialize,
- CustomLayerRenderFunction render,
+ CustomLayerRenderFunction render_,
CustomLayerDeinitializeFunction deinitialize,
void* context_,
const char* before) {
- context->invoke(&MapContext::addLayer,
- std::make_unique<CustomLayer>(id, initialize, render, deinitialize, context_),
+ view.activate();
+ context->addLayer(
+ std::make_unique<CustomLayer>(id, initialize, render_, deinitialize, context_),
before ? std::string(before) : optional<std::string>());
+ view.deactivate();
}
void Map::removeCustomLayer(const std::string& id) {
- context->invoke(&MapContext::removeLayer, id);
+ view.activate();
+ context->removeLayer(id);
+ view.deactivate();
}
#pragma mark - Toggles
@@ -519,39 +499,39 @@ MapDebugOptions Map::getDebug() const {
}
bool Map::isFullyLoaded() const {
- return context->invokeSync<bool>(&MapContext::isLoaded);
+ return context->isLoaded();
}
void Map::addClass(const std::string& className, const PropertyTransition& properties) {
- context->invoke(&MapContext::addClass, className, properties);
+ context->addClass(className, properties);
}
void Map::removeClass(const std::string& className, const PropertyTransition& properties) {
- context->invoke(&MapContext::removeClass, className, properties);
+ context->removeClass(className, properties);
}
void Map::setClasses(const std::vector<std::string>& classNames, const PropertyTransition& properties) {
- context->invoke(&MapContext::setClasses, classNames, properties);
+ context->setClasses(classNames, properties);
}
bool Map::hasClass(const std::string& className) const {
- return context->invokeSync<bool>(&MapContext::hasClass, className);
+ return context->hasClass(className);
}
std::vector<std::string> Map::getClasses() const {
- return context->invokeSync<std::vector<std::string>>(&MapContext::getClasses);
+ return context->getClasses();
}
void Map::setSourceTileCacheSize(size_t size) {
- context->invoke(&MapContext::setSourceTileCacheSize, size);
+ context->setSourceTileCacheSize(size);
}
void Map::onLowMemory() {
- context->invoke(&MapContext::onLowMemory);
+ context->onLowMemory();
}
void Map::dumpDebugLogs() const {
- context->invokeSync(&MapContext::dumpDebugLogs);
+ context->dumpDebugLogs();
}
} // namespace mbgl
diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp
index 0ea51bf53a..2ff93d2338 100644
--- a/src/mbgl/map/map_context.cpp
+++ b/src/mbgl/map/map_context.cpp
@@ -35,11 +35,7 @@ MapContext::MapContext(View& view_, FileSource& fileSource_, MapMode mode_, GLCo
dataPtr(std::make_unique<MapData>(mode_, contextMode_, pixelRatio_)),
data(*dataPtr),
asyncUpdate([this] { update(); }),
- asyncInvalidate([&view_] { view_.invalidate(); }),
texturePool(std::make_unique<gl::TexturePool>()) {
- assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
-
- view.activate();
}
MapContext::~MapContext() {
@@ -48,7 +44,7 @@ MapContext::~MapContext() {
}
void MapContext::cleanup() {
- view.notify();
+ view.activate();
styleRequest = nullptr;
@@ -64,21 +60,6 @@ void MapContext::cleanup() {
view.deactivate();
}
-void MapContext::pause() {
- MBGL_CHECK_ERROR(glFinish());
-
- view.deactivate();
-
- std::unique_lock<std::mutex> lockPause(data.mutexPause);
- data.paused = true;
- data.condPause.notify_all();
- data.condPause.wait(lockPause, [&]{ return !data.paused; });
-
- view.activate();
-
- asyncInvalidate.send();
-}
-
void MapContext::updateAsync(Update flags) {
updateFlags |= flags;
asyncUpdate.send();
@@ -180,9 +161,11 @@ void MapContext::update() {
style->update(transformState, frameData.timePoint, *texturePool);
if (data.mode == MapMode::Continuous) {
- asyncInvalidate.send();
+ view.invalidate();
} else if (callback && isLoaded()) {
+ view.activate();
renderSync(transformState, frameData);
+ view.deactivate();
}
updateFlags = Update::Nothing;
@@ -229,8 +212,6 @@ bool MapContext::renderSync(const TransformState& state, const FrameData& frame)
return false;
}
- view.beforeRender();
-
transformState = state;
frameData = frame;
@@ -245,8 +226,6 @@ bool MapContext::renderSync(const TransformState& state, const FrameData& frame)
// Cleanup OpenGL objects that we abandoned since the last render call.
glObjectStore.performCleanup();
- view.afterRender();
-
if (style->hasTransitions()) {
updateAsync(Update::RecalculateStyle);
} else if (painter->needsAnimation()) {
@@ -312,7 +291,7 @@ void MapContext::setSourceTileCacheSize(size_t size) {
sourceCacheSize = size;
if (!style) return;
style->setSourceTileCacheSize(size);
- asyncInvalidate.send();
+ view.invalidate();
}
}
@@ -320,7 +299,7 @@ void MapContext::onLowMemory() {
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
if (!style) return;
style->onLowMemory();
- asyncInvalidate.send();
+ view.invalidate();
}
void MapContext::onResourceLoaded() {
diff --git a/src/mbgl/map/map_context.hpp b/src/mbgl/map/map_context.hpp
index 5e1d5e70ae..93e7a52b25 100644
--- a/src/mbgl/map/map_context.hpp
+++ b/src/mbgl/map/map_context.hpp
@@ -37,8 +37,6 @@ public:
MapData& getData() { return data; }
- void pause();
-
void triggerUpdate(const TransformState&, Update = Update::Nothing);
void renderStill(const TransformState&, const FrameData&, Map::StillImageCallback callback);
@@ -97,7 +95,6 @@ private:
Update updateFlags = Update::Nothing;
util::AsyncTask asyncUpdate;
- util::AsyncTask asyncInvalidate;
std::unique_ptr<gl::TexturePool> texturePool;
std::unique_ptr<Painter> painter;
diff --git a/src/mbgl/map/map_data.hpp b/src/mbgl/map/map_data.hpp
index 0513d84f87..63a9dbd1e1 100644
--- a/src/mbgl/map/map_data.hpp
+++ b/src/mbgl/map/map_data.hpp
@@ -1,11 +1,8 @@
#ifndef MBGL_MAP_MAP_DATA
#define MBGL_MAP_MAP_DATA
-#include <mutex>
-#include <atomic>
#include <vector>
#include <cassert>
-#include <condition_variable>
#include <mbgl/map/mode.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
@@ -14,8 +11,6 @@
namespace mbgl {
class MapData {
- using Lock = std::lock_guard<std::mutex>;
-
public:
inline MapData(MapMode mode_, GLContextMode contextMode_, const float pixelRatio_)
: mode(mode_)
@@ -46,10 +41,8 @@ public:
debugOptions = debugOptions_;
}
- util::exclusive<AnnotationManager> getAnnotationManager() {
- return util::exclusive<AnnotationManager>(
- &annotationManager,
- std::make_unique<std::lock_guard<std::mutex>>(annotationManagerMutex));
+ AnnotationManager* getAnnotationManager() {
+ return &annotationManager;
}
public:
@@ -58,16 +51,12 @@ public:
const float pixelRatio;
private:
- mutable std::mutex annotationManagerMutex;
AnnotationManager annotationManager;
- std::atomic<MapDebugOptions> debugOptions { MapDebugOptions::NoDebug };
+ MapDebugOptions debugOptions { MapDebugOptions::NoDebug };
// TODO: make private
public:
- bool paused = false;
- std::mutex mutexPause;
- std::condition_variable condPause;
};
} // namespace mbgl
diff --git a/src/mbgl/util/thread_context.hpp b/src/mbgl/util/thread_context.hpp
index dea98fe3fa..bd591e88a5 100644
--- a/src/mbgl/util/thread_context.hpp
+++ b/src/mbgl/util/thread_context.hpp
@@ -15,7 +15,7 @@ enum class ThreadPriority : bool {
enum class ThreadType : uint8_t {
Main,
- Map,
+ Map = Main,
Worker,
Unknown,
};
diff --git a/test/api/annotations.cpp b/test/api/annotations.cpp
index 0af64095c1..f403512660 100644
--- a/test/api/annotations.cpp
+++ b/test/api/annotations.cpp
@@ -8,6 +8,7 @@
#include <mbgl/platform/default/headless_view.hpp>
#include <mbgl/storage/online_file_source.hpp>
#include <mbgl/util/io.hpp>
+#include <mbgl/util/run_loop.hpp>
#include <future>
#include <vector>
@@ -29,6 +30,8 @@ void checkRendering(Map& map, const char * name) {
} // end namespace
TEST(Annotations, PointAnnotation) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -42,6 +45,8 @@ TEST(Annotations, PointAnnotation) {
}
TEST(Annotations, LineAnnotation) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -61,6 +66,8 @@ TEST(Annotations, LineAnnotation) {
}
TEST(Annotations, FillAnnotation) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -79,6 +86,8 @@ TEST(Annotations, FillAnnotation) {
}
TEST(Annotations, StyleSourcedShapeAnnotation) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -94,6 +103,8 @@ TEST(Annotations, StyleSourcedShapeAnnotation) {
}
TEST(Annotations, AddMultiple) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -111,6 +122,8 @@ TEST(Annotations, AddMultiple) {
}
TEST(Annotations, NonImmediateAdd) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -131,6 +144,8 @@ TEST(Annotations, NonImmediateAdd) {
}
TEST(Annotations, UpdateIcon) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -150,6 +165,8 @@ TEST(Annotations, UpdateIcon) {
}
TEST(Annotations, UpdatePoint) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -168,6 +185,8 @@ TEST(Annotations, UpdatePoint) {
}
TEST(Annotations, RemovePoint) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -185,6 +204,8 @@ TEST(Annotations, RemovePoint) {
}
TEST(Annotations, RemoveShape) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -207,6 +228,8 @@ TEST(Annotations, RemoveShape) {
}
TEST(Annotations, ImmediateRemoveShape) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
@@ -219,6 +242,8 @@ TEST(Annotations, ImmediateRemoveShape) {
}
TEST(Annotations, SwitchStyle) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
diff --git a/test/api/api_misuse.cpp b/test/api/api_misuse.cpp
index 932c4717e8..5e413df369 100644
--- a/test/api/api_misuse.cpp
+++ b/test/api/api_misuse.cpp
@@ -6,6 +6,7 @@
#include <mbgl/platform/default/headless_view.hpp>
#include <mbgl/storage/online_file_source.hpp>
#include <mbgl/util/exception.hpp>
+#include <mbgl/util/run_loop.hpp>
#include <future>
@@ -15,6 +16,8 @@ TEST(API, RenderWithoutCallback) {
FixtureLogObserver* log = new FixtureLogObserver();
Log::setObserver(std::unique_ptr<Log::Observer>(log));
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
view.resize(128, 512);
@@ -37,6 +40,8 @@ TEST(API, RenderWithoutCallback) {
}
TEST(API, RenderWithoutStyle) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
view.resize(128, 512);
@@ -44,13 +49,16 @@ TEST(API, RenderWithoutStyle) {
Map map(view, fileSource, MapMode::Still);
- std::promise<std::exception_ptr> promise;
- map.renderStill([&promise](std::exception_ptr error, PremultipliedImage&&) {
- promise.set_value(error);
+ std::exception_ptr error;
+ map.renderStill([&](std::exception_ptr error_, PremultipliedImage&&) {
+ error = error_;
+ loop.stop();
});
+ loop.run();
+
try {
- std::rethrow_exception(promise.get_future().get());
+ std::rethrow_exception(error);
} catch (const util::MisuseException& ex) {
EXPECT_EQ(std::string(ex.what()), "Map doesn't have a style");
} catch (const std::exception&) {
diff --git a/test/api/custom_layer.cpp b/test/api/custom_layer.cpp
index 5346fee124..46eecb2250 100644
--- a/test/api/custom_layer.cpp
+++ b/test/api/custom_layer.cpp
@@ -7,6 +7,7 @@
#include <mbgl/layer/custom_layer.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/run_loop.hpp>
using namespace mbgl;
@@ -68,6 +69,8 @@ public:
};
TEST(CustomLayer, Basic) {
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
diff --git a/test/api/render_missing.cpp b/test/api/render_missing.cpp
index f29a0c2b9c..bb14416840 100644
--- a/test/api/render_missing.cpp
+++ b/test/api/render_missing.cpp
@@ -7,6 +7,7 @@
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
+#include <mbgl/util/run_loop.hpp>
#include <future>
@@ -19,6 +20,8 @@
TEST(API, TEST_REQUIRES_SERVER(RenderMissingTile)) {
using namespace mbgl;
+ util::RunLoop loop;
+
const auto style = util::read_file("test/fixtures/api/water_missing_tiles.json");
auto display = std::make_shared<mbgl::HeadlessDisplay>();
@@ -38,8 +41,7 @@ TEST(API, TEST_REQUIRES_SERVER(RenderMissingTile)) {
// This host does not respond (== connection error).
map.setStyleJSON(style, "");
- std::promise<void> promise;
- map.renderStill([&promise, &message](std::exception_ptr err, PremultipliedImage&&) {
+ map.renderStill([&](std::exception_ptr err, PremultipliedImage&&) {
ASSERT_TRUE(err.operator bool());
try {
std::rethrow_exception(err);
@@ -47,9 +49,10 @@ TEST(API, TEST_REQUIRES_SERVER(RenderMissingTile)) {
message = ex.what();
EXPECT_TRUE(message.find("connect") != std::string::npos);
}
- promise.set_value();
+ loop.stop();
});
- promise.get_future().get();
+
+ loop.run();
auto observer = Log::removeObserver();
auto flo = dynamic_cast<FixtureLogObserver*>(observer.get());
diff --git a/test/api/repeated_render.cpp b/test/api/repeated_render.cpp
index ef707aa7c4..cf5d115997 100644
--- a/test/api/repeated_render.cpp
+++ b/test/api/repeated_render.cpp
@@ -7,12 +7,15 @@
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
+#include <mbgl/util/run_loop.hpp>
#include <future>
TEST(API, RepeatedRender) {
using namespace mbgl;
+ util::RunLoop loop;
+
const auto style = util::read_file("test/fixtures/api/water.json");
auto display = std::make_shared<mbgl::HeadlessDisplay>();
@@ -30,11 +33,15 @@ TEST(API, RepeatedRender) {
{
map.setStyleJSON(style, "");
- std::promise<PremultipliedImage> promise;
- map.renderStill([&promise](std::exception_ptr, PremultipliedImage&& image) {
- promise.set_value(std::move(image));
+ PremultipliedImage result;
+ map.renderStill([&result](std::exception_ptr, PremultipliedImage&& image) {
+ result = std::move(image);
});
- auto result = promise.get_future().get();
+
+ while (!result.size()) {
+ loop.runOnce();
+ }
+
ASSERT_EQ(256, result.width);
ASSERT_EQ(512, result.height);
#if !TEST_READ_ONLY
@@ -44,11 +51,15 @@ TEST(API, RepeatedRender) {
{
map.setStyleJSON(style, "");
- std::promise<PremultipliedImage> promise;
- map.renderStill([&promise](std::exception_ptr, PremultipliedImage&& image) {
- promise.set_value(std::move(image));
+ PremultipliedImage result;
+ map.renderStill([&result](std::exception_ptr, PremultipliedImage&& image) {
+ result = std::move(image);
});
- auto result = promise.get_future().get();
+
+ while (!result.size()) {
+ loop.runOnce();
+ }
+
ASSERT_EQ(256, result.width);
ASSERT_EQ(512, result.height);
#if !TEST_READ_ONLY
diff --git a/test/api/set_style.cpp b/test/api/set_style.cpp
index 329ec2801d..317021b8db 100644
--- a/test/api/set_style.cpp
+++ b/test/api/set_style.cpp
@@ -5,11 +5,14 @@
#include <mbgl/platform/default/headless_view.hpp>
#include <mbgl/platform/default/headless_display.hpp>
#include <mbgl/storage/online_file_source.hpp>
+#include <mbgl/util/run_loop.hpp>
TEST(API, SetStyle) {
using namespace mbgl;
+ util::RunLoop loop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
OnlineFileSource fileSource;
diff --git a/test/map/map.cpp b/test/map/map.cpp
index b1048e97e2..2bc00b4334 100644
--- a/test/map/map.cpp
+++ b/test/map/map.cpp
@@ -3,59 +3,17 @@
#include <mbgl/map/map.hpp>
#include <mbgl/platform/default/headless_view.hpp>
#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/storage/online_file_source.hpp>
#include <mbgl/storage/network_status.hpp>
-#include <mbgl/storage/offline_database.hpp>
#include <mbgl/storage/default_file_source.hpp>
#include <mbgl/util/io.hpp>
+#include <mbgl/util/run_loop.hpp>
using namespace mbgl;
using namespace std::literals::string_literals;
-TEST(Map, PauseResume) {
- auto display = std::make_shared<mbgl::HeadlessDisplay>();
- HeadlessView view(display, 1);
- OnlineFileSource fileSource;
-
- Map map(view, fileSource, MapMode::Continuous);
-
- map.pause();
- map.resume();
-}
-
-TEST(Map, DoublePause) {
- auto display = std::make_shared<mbgl::HeadlessDisplay>();
- HeadlessView view(display, 1);
- OnlineFileSource fileSource;
-
- Map map(view, fileSource, MapMode::Continuous);
-
- map.pause();
- map.pause();
- map.resume();
-}
-
-TEST(Map, ResumeWithoutPause) {
- auto display = std::make_shared<mbgl::HeadlessDisplay>();
- HeadlessView view(display, 1);
- OnlineFileSource fileSource;
-
- Map map(view, fileSource, MapMode::Continuous);
-
- map.resume();
-}
-
-TEST(Map, DestroyPaused) {
- auto display = std::make_shared<mbgl::HeadlessDisplay>();
- HeadlessView view(display, 1);
- OnlineFileSource fileSource;
-
- Map map(view, fileSource, MapMode::Continuous);
-
- map.pause();
-}
-
TEST(Map, Offline) {
+ util::RunLoop runLoop;
+
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display, 1);
DefaultFileSource fileSource(":memory:", ".");
diff --git a/test/src/mbgl/test/mock_view.hpp b/test/src/mbgl/test/mock_view.hpp
index e608545da5..50ae466d19 100644
--- a/test/src/mbgl/test/mock_view.hpp
+++ b/test/src/mbgl/test/mock_view.hpp
@@ -18,10 +18,7 @@ public:
void activate() override {};
void deactivate() override {};
- void notify() override {};
void invalidate() override {}
- void beforeRender() override {}
- void afterRender() override {}
};
}
diff --git a/test/src/mbgl/test/util.cpp b/test/src/mbgl/test/util.cpp
index ca2282a4b5..4021fd89b1 100644
--- a/test/src/mbgl/test/util.cpp
+++ b/test/src/mbgl/test/util.cpp
@@ -5,6 +5,7 @@
#include <mbgl/util/image.hpp>
#include <mbgl/util/io.hpp>
#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/run_loop.hpp>
#include <mapbox/pixelmatch.hpp>
@@ -86,11 +87,16 @@ Server::~Server() {
}
PremultipliedImage render(Map& map) {
- std::promise<PremultipliedImage> promise;
- map.renderStill([&](std::exception_ptr, PremultipliedImage&& image) {
- promise.set_value(std::move(image));
+ PremultipliedImage result;
+ map.renderStill([&result](std::exception_ptr, PremultipliedImage&& image) {
+ result = std::move(image);
});
- return promise.get_future().get();
+
+ while (!result.size()) {
+ util::RunLoop::Get()->runOnce();
+ }
+
+ return result;
}
void checkImage(const std::string& base,
diff --git a/test/test.gypi b/test/test.gypi
index 42dab6432c..6b3b43bd0c 100644
--- a/test/test.gypi
+++ b/test/test.gypi
@@ -41,7 +41,6 @@
'geometry/binpack.cpp',
- 'map/map.cpp',
'map/map_context.cpp',
'map/tile.cpp',
'map/transform.cpp',