summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2015-03-11 19:43:13 +0100
committerKonstantin Käfer <mail@kkaefer.com>2015-03-12 12:16:38 +0100
commit47ede853c4c0dd8e953f3ee98b807f044d178d76 (patch)
tree75d56f01853cb64b200d8977069dfe992266e9de /src
parentba9d2420699507c6d32b12272151529663c8d2fd (diff)
downloadqtlocation-mapboxgl-47ede853c4c0dd8e953f3ee98b807f044d178d76.tar.gz
fixes black flicker on rotating the device
fixes #838 instead of rendering ad libitum on the map thread, we are now driving rendering from the UI thread on iOS via the map.renderSync() function. There are still white bars during the rotation, but the general content of the view is kept visible. - upgrades GLFW to 3.1 - removes swapped/needsSwap in favor of a more explicit scheme - View#invalidate() now replaces View#swap() and is called whenever the View needs to trigger a rerender. GLFW and Android to this right away, while iOS goes back to the main thread and does the Map redrawing as part of the GLKView update - sets all iOS deployment targets to 7.0 - disables SQLite3 version check, since the library version changed on iOS 8.2
Diffstat (limited to 'src')
-rw-r--r--src/mbgl/map/map.cpp153
-rw-r--r--src/mbgl/map/source.cpp6
-rw-r--r--src/mbgl/map/view.cpp10
3 files changed, 94 insertions, 75 deletions
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 0cd7d3621e..29521f9499 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -73,10 +73,6 @@ Map::Map(View& view_, FileSource& fileSource_)
painter(util::make_unique<Painter>(*spriteAtlas, *glyphAtlas, *lineAtlas))
{
view.initialize(this);
- // Make sure that we're doing an initial drawing in all cases.
- isClean.clear();
- isRendered.clear();
- isSwapped.test_and_set();
}
Map::~Map() {
@@ -124,28 +120,32 @@ void Map::start(bool startPaused) {
// Closes all open handles on the loop. This means that the loop will automatically terminate.
asyncRender.reset();
+ asyncUpdate.reset();
asyncTerminate.reset();
});
- asyncRender = util::make_unique<uv::async>(env->loop, [this]() {
+ asyncUpdate = util::make_unique<uv::async>(env->loop, [this] {
assert(std::this_thread::get_id() == mapThread);
if (state.hasSize()) {
- if (isRendered.test_and_set() == false) {
- prepare();
- if (isClean.test_and_set() == false) {
- render();
- isSwapped.clear();
- view.swap();
- } else {
- // We set the rendered flag in the test above, so we have to reset it
- // now that we're not actually rendering because the map is clean.
- isRendered.clear();
- }
- }
+ prepare();
}
});
+ asyncRender = util::make_unique<uv::async>(env->loop, [this] {
+ // Must be called in Map thread.
+ assert(std::this_thread::get_id() == mapThread);
+
+ render();
+
+ // Finally, notify all listeners that we have finished rendering this frame.
+ {
+ std::lock_guard<std::mutex> lk(mutexRendered);
+ rendered = true;
+ }
+ condRendered.notify_all();
+ });
+
// Do we need to pause first?
if (startPaused) {
pause();
@@ -208,7 +208,7 @@ void Map::pause(bool waitForPause) {
mutexRun.unlock();
uv_stop(env->loop);
- rerender(); // Needed to ensure uv_stop is seen and uv_run exits, otherwise we deadlock on wait_for_pause
+ triggerUpdate(); // Needed to ensure uv_stop is seen and uv_run exits, otherwise we deadlock on wait_for_pause
if (waitForPause) {
std::unique_lock<std::mutex> lockPause (mutexPause);
@@ -280,6 +280,30 @@ void Map::run() {
view.deactivate();
}
+void Map::renderSync() {
+ // Must be called in UI thread.
+ assert(std::this_thread::get_id() == mainThread);
+
+ triggerRender();
+
+ std::unique_lock<std::mutex> lock(mutexRendered);
+ condRendered.wait(lock, [this] { return rendered; });
+ rendered = false;
+}
+
+void Map::triggerUpdate() {
+ if (mode == Mode::Static) {
+ prepare();
+ } else if (asyncUpdate) {
+ asyncUpdate->send();
+ }
+}
+
+void Map::triggerRender() {
+ assert(asyncRender);
+ asyncRender->send();
+}
+
void Map::checkForPause() {
std::unique_lock<std::mutex> lockRun (mutexRun);
while (pausing) {
@@ -300,32 +324,6 @@ void Map::checkForPause() {
mutexPause.unlock();
}
-void Map::rerender() {
- if (mode == Mode::Static) {
- prepare();
- } else if (mode == Mode::Continuous) {
- // We only send render events if we want to continuously update the map
- // (== async rendering).
- if (asyncRender) {
- asyncRender->send();
- }
- }
-}
-
-void Map::update() {
- isClean.clear();
- rerender();
-}
-
-bool Map::needsSwap() {
- return isSwapped.test_and_set() == false;
-}
-
-void Map::swapped() {
- isRendered.clear();
- rerender();
-}
-
void Map::terminate() {
assert(painter);
painter->terminate();
@@ -350,7 +348,6 @@ void Map::setStyleURL(const std::string &url) {
}
}
-
void Map::setStyleJSON(std::string newStyleJSON, const std::string &base) {
// TODO: Make threadsafe.
styleJSON.swap(newStyleJSON);
@@ -367,7 +364,7 @@ void Map::setStyleJSON(std::string newStyleJSON, const std::string &base) {
const std::string glyphURL = util::mapbox::normalizeGlyphsURL(style->glyph_url, getAccessToken());
glyphStore->setURL(glyphURL);
- update();
+ triggerUpdate();
}
std::string Map::getStyleJSON() const {
@@ -393,7 +390,7 @@ void Map::resize(uint16_t width, uint16_t height, float ratio) {
void Map::resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight) {
if (transform.resize(width, height, ratio, fbWidth, fbHeight)) {
- update();
+ triggerUpdate();
}
}
@@ -402,7 +399,7 @@ void Map::resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth,
void Map::cancelTransitions() {
transform.cancelTransitions();
- update();
+ triggerUpdate();
}
@@ -410,12 +407,12 @@ void Map::cancelTransitions() {
void Map::moveBy(double dx, double dy, std::chrono::steady_clock::duration duration) {
transform.moveBy(dx, dy, duration);
- update();
+ triggerUpdate();
}
void Map::setLatLng(LatLng latLng, std::chrono::steady_clock::duration duration) {
transform.setLatLng(latLng, duration);
- update();
+ triggerUpdate();
}
LatLng Map::getLatLng() const {
@@ -424,19 +421,19 @@ LatLng Map::getLatLng() const {
void Map::startPanning() {
transform.startPanning();
- update();
+ triggerUpdate();
}
void Map::stopPanning() {
transform.stopPanning();
- update();
+ triggerUpdate();
}
void Map::resetPosition() {
transform.setAngle(0);
transform.setLatLng(LatLng(0, 0));
transform.setZoom(0);
- update();
+ triggerUpdate();
}
@@ -444,12 +441,12 @@ void Map::resetPosition() {
void Map::scaleBy(double ds, double cx, double cy, std::chrono::steady_clock::duration duration) {
transform.scaleBy(ds, cx, cy, duration);
- update();
+ triggerUpdate();
}
void Map::setScale(double scale, double cx, double cy, std::chrono::steady_clock::duration duration) {
transform.setScale(scale, cx, cy, duration);
- update();
+ triggerUpdate();
}
double Map::getScale() const {
@@ -458,7 +455,7 @@ double Map::getScale() const {
void Map::setZoom(double zoom, std::chrono::steady_clock::duration duration) {
transform.setZoom(zoom, duration);
- update();
+ triggerUpdate();
}
double Map::getZoom() const {
@@ -467,7 +464,7 @@ double Map::getZoom() const {
void Map::setLatLngZoom(LatLng latLng, double zoom, std::chrono::steady_clock::duration duration) {
transform.setLatLngZoom(latLng, zoom, duration);
- update();
+ triggerUpdate();
}
void Map::resetZoom() {
@@ -476,12 +473,12 @@ void Map::resetZoom() {
void Map::startScaling() {
transform.startScaling();
- update();
+ triggerUpdate();
}
void Map::stopScaling() {
transform.stopScaling();
- update();
+ triggerUpdate();
}
double Map::getMinZoom() const {
@@ -497,17 +494,17 @@ double Map::getMaxZoom() const {
void Map::rotateBy(double sx, double sy, double ex, double ey, std::chrono::steady_clock::duration duration) {
transform.rotateBy(sx, sy, ex, ey, duration);
- update();
+ triggerUpdate();
}
void Map::setBearing(double degrees, std::chrono::steady_clock::duration duration) {
transform.setAngle(-degrees * M_PI / 180, duration);
- update();
+ triggerUpdate();
}
void Map::setBearing(double degrees, double cx, double cy) {
transform.setAngle(-degrees * M_PI / 180, cx, cy);
- update();
+ triggerUpdate();
}
double Map::getBearing() const {
@@ -516,17 +513,17 @@ double Map::getBearing() const {
void Map::resetNorth() {
transform.setAngle(0, std::chrono::milliseconds(500));
- update();
+ triggerUpdate();
}
void Map::startRotating() {
transform.startRotating();
- update();
+ triggerUpdate();
}
void Map::stopRotating() {
transform.stopRotating();
- update();
+ triggerUpdate();
}
#pragma mark - Access Token
@@ -545,7 +542,7 @@ void Map::setDebug(bool value) {
debug = value;
assert(painter);
painter->setDebug(debug);
- update();
+ triggerUpdate();
}
void Map::toggleDebug() {
@@ -562,7 +559,7 @@ void Map::addClass(const std::string& klass) {
if (style) {
style->cascadeClasses(classes);
if (style->hasTransitions()) {
- update();
+ triggerUpdate();
}
}
}
@@ -573,7 +570,7 @@ void Map::removeClass(const std::string& klass) {
if (style) {
style->cascadeClasses(classes);
if (style->hasTransitions()) {
- update();
+ triggerUpdate();
}
}
}
@@ -583,7 +580,7 @@ void Map::setClasses(const std::vector<std::string>& classes_) {
if (style) {
style->cascadeClasses(classes);
if (style->hasTransitions()) {
- update();
+ triggerUpdate();
}
}
}
@@ -637,6 +634,7 @@ void Map::updateSources() {
}
void Map::updateSources(const util::ptr<StyleLayerGroup> &group) {
+ assert(std::this_thread::get_id() == mapThread);
if (!group) {
return;
}
@@ -649,13 +647,19 @@ void Map::updateSources(const util::ptr<StyleLayerGroup> &group) {
}
void Map::updateTiles() {
- for (const auto& source : activeSources) {
+ assert(std::this_thread::get_id() == mapThread);
+ for (const auto &source : activeSources) {
source->source->update(*this, *env, getWorker(), style, *glyphAtlas, *glyphStore,
- *spriteAtlas, getSprite(), *texturePool, [this]() { update(); });
+ *spriteAtlas, getSprite(), *texturePool, [this]() {
+ assert(std::this_thread::get_id() == mapThread);
+ triggerUpdate();
+ });
}
}
void Map::prepare() {
+ assert(std::this_thread::get_id() == mapThread);
+
if (!style) {
style = std::make_shared<Style>();
@@ -692,14 +696,19 @@ void Map::prepare() {
spriteAtlas->setSprite(getSprite());
updateTiles();
+
+ if (mode == Mode::Continuous) {
+ view.invalidate();
+ }
}
void Map::render() {
+ assert(std::this_thread::get_id() == mapThread);
assert(painter);
painter->render(*style, activeSources,
state, animationTime);
// Schedule another rerender when we definitely need a next frame.
if (transform.needsTransition() || style->hasTransitions()) {
- update();
+ triggerUpdate();
}
}
diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp
index ec3a1b8e00..447f25d4b7 100644
--- a/src/mbgl/map/source.cpp
+++ b/src/mbgl/map/source.cpp
@@ -60,8 +60,7 @@ void Source::load(Map &map, Environment &env) {
source->info.parseTileJSONProperties(d);
source->loaded = true;
- map.update();
-
+ map.triggerUpdate();
});
}
@@ -293,8 +292,9 @@ void Source::update(Map &map,
util::ptr<Sprite> sprite,
TexturePool &texturePool,
std::function<void()> callback) {
- if (!loaded || map.getTime() <= updated)
+ if (!loaded || map.getTime() <= updated) {
return;
+ }
bool changed = false;
diff --git a/src/mbgl/map/view.cpp b/src/mbgl/map/view.cpp
index 3927652ba6..21ba4daf36 100644
--- a/src/mbgl/map/view.cpp
+++ b/src/mbgl/map/view.cpp
@@ -3,9 +3,19 @@
namespace mbgl {
+void View::initialize(Map *map_) {
+ assert(map_);
+ map = map_;
+}
+
void View::resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight) {
assert(map);
map->resize(width, height, ratio, fbWidth, fbHeight);
}
+void View::notifyMapChange(MapChange, std::chrono::steady_clock::duration) {
+ // no-op
+}
+
+
}