#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mbgl { MapContext::MapContext(uv_loop_t* loop, Environment& env_, View& view_, MapData& data_, bool startPaused) : env(env_), view(view_), data(data_), mapScope(env, ThreadType::Map, "Map"), updated(static_cast(Update::Nothing)), asyncUpdate(util::make_unique(loop, [this] { update(); })), workers(util::make_unique(loop, 4)), glyphStore(util::make_unique(env)), glyphAtlas(util::make_unique(1024, 1024)), spriteAtlas(util::make_unique(512, 512)), lineAtlas(util::make_unique(512, 512)), texturePool(util::make_unique()), painter(util::make_unique(*spriteAtlas, *glyphAtlas, *lineAtlas)) { assert(Environment::currentlyOn(ThreadType::Map)); asyncUpdate->unref(); view.activate(); if (startPaused) { pause(); } painter->setup(); } MapContext::~MapContext() { view.deactivate(); view.notify(); // Explicit resets currently necessary because these abandon resources that need to be // cleaned up by env.performCleanup(); style.reset(); sprite.reset(); painter.reset(); texturePool.reset(); lineAtlas.reset(); spriteAtlas.reset(); glyphAtlas.reset(); glyphStore.reset(); env.performCleanup(); } void MapContext::pause() { view.deactivate(); std::unique_lock lockPause(data.mutexPause); data.condPaused.notify_all(); data.condResume.wait(lockPause); view.activate(); } void MapContext::resize(uint16_t width, uint16_t height, float ratio) { view.resize(width, height, ratio); triggerUpdate(); } void MapContext::triggerUpdate(const Update u) { updated |= static_cast(u); asyncUpdate->send(); } void MapContext::setStyleURL(const std::string& url) { styleURL = mbgl::util::mapbox::normalizeStyleURL(url, data.getAccessToken()); styleJSON.clear(); const size_t pos = styleURL.rfind('/'); std::string base = ""; if (pos != std::string::npos) { base = styleURL.substr(0, pos + 1); } env.request({ Resource::Kind::JSON, styleURL }, [this, base](const Response &res) { if (res.status == Response::Successful) { loadStyleJSON(res.data, base); } else { Log::Error(Event::Setup, "loading style failed: %s", res.message.c_str()); } }); } void MapContext::setStyleJSON(const std::string& json, const std::string& base) { styleURL.clear(); styleJSON = json; loadStyleJSON(json, base); } util::ptr MapContext::getSprite() { assert(Environment::currentlyOn(ThreadType::Map)); const float pixelRatio = transformState.getPixelRatio(); const std::string &sprite_url = style->getSpriteURL(); if (!sprite || !sprite->hasPixelRatio(pixelRatio)) { sprite = std::make_shared(sprite_url, pixelRatio, env, [this] { assert(Environment::currentlyOn(ThreadType::Map)); triggerUpdate(); }); } return sprite; } void MapContext::loadStyleJSON(const std::string& json, const std::string& base) { assert(Environment::currentlyOn(ThreadType::Map)); sprite.reset(); style = std::make_shared