From da81211feaffd89319330774b61b261b939dde33 Mon Sep 17 00:00:00 2001 From: "Thiago Marcos P. Santos" Date: Tue, 19 May 2015 01:13:46 +0300 Subject: [PATCH] Add callback for error notifications on renderStill() The callback will be called when any of the resources requested from the network failed to load. There is not recovery implemented yet, so the closest thing to reseting the Map object and reloading all the resources would be setting a new style. --- bin/render.cpp | 11 ++++++++++- include/mbgl/map/map.hpp | 2 +- include/mbgl/platform/event.hpp | 2 ++ src/mbgl/map/map_context.cpp | 11 ++++++++++- src/mbgl/map/map_context.hpp | 3 ++- src/mbgl/map/resource_loader.cpp | 16 ++++++++++++++++ src/mbgl/map/resource_loader.hpp | 2 ++ test/api/repeated_render.cpp | 4 ++-- test/headless/headless.cpp | 2 +- 9 files changed, 46 insertions(+), 7 deletions(-) diff --git a/bin/render.cpp b/bin/render.cpp index 33e216f52..740d3dffe 100644 --- a/bin/render.cpp +++ b/bin/render.cpp @@ -111,7 +111,16 @@ int main(int argc, char *argv[]) { util::write_file(output, png); }); - map.renderStill([async](std::unique_ptr image) { + map.renderStill([async](std::exception_ptr error, std::unique_ptr image) { + try { + if (error) { + std::rethrow_exception(error); + } + } catch(std::exception& e) { + std::cout << "Error: " << e.what() << std::endl; + exit(1); + } + async->data = const_cast(image.release()); uv_async_send(async); }); diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp index e71c5f5b4..a6aac08b3 100644 --- a/include/mbgl/map/map.hpp +++ b/include/mbgl/map/map.hpp @@ -42,7 +42,7 @@ public: // 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)>; + using StillImageCallback = std::function)>; void renderStill(StillImageCallback callback); // Triggers a synchronous or asynchronous render. diff --git a/include/mbgl/platform/event.hpp b/include/mbgl/platform/event.hpp index 5fd64119c..8cdd1d50a 100644 --- a/include/mbgl/platform/event.hpp +++ b/include/mbgl/platform/event.hpp @@ -29,6 +29,7 @@ enum class Event : uint8_t { ParseStyle, ParseTile, Render, + ResourceLoader, Database, HttpRequest, Sprite, @@ -46,6 +47,7 @@ MBGL_DEFINE_ENUM_CLASS(EventClass, Event, { { Event::ParseStyle, "ParseStyle" }, { Event::ParseTile, "ParseTile" }, { Event::Render, "Render" }, + { Event::ResourceLoader, "ResourceLoader" }, { Event::Database, "Database" }, { Event::HttpRequest, "HttpRequest" }, { Event::Sprite, "Sprite" }, diff --git a/src/mbgl/map/map_context.cpp b/src/mbgl/map/map_context.cpp index f373274eb..28bd8903e 100644 --- a/src/mbgl/map/map_context.cpp +++ b/src/mbgl/map/map_context.cpp @@ -232,7 +232,7 @@ void MapContext::render() { painter->render(*style, transformState, data.getAnimationTime()); if (data.mode == MapMode::Still) { - callback(view.readStillImage()); + callback(nullptr, view.readStillImage()); callback = nullptr; } @@ -274,4 +274,13 @@ void MapContext::onTileDataChanged() { triggerUpdate(); } +void MapContext::onResourceLoadingFailed(std::exception_ptr error) { + assert(Environment::currentlyOn(ThreadType::Map)); + + if (data.mode == MapMode::Still && callback) { + callback(error, nullptr); + callback = nullptr; + } +} + } diff --git a/src/mbgl/map/map_context.hpp b/src/mbgl/map/map_context.hpp index c84245484..fb9fdb4d4 100644 --- a/src/mbgl/map/map_context.hpp +++ b/src/mbgl/map/map_context.hpp @@ -43,7 +43,7 @@ public: void resize(uint16_t width, uint16_t height, float ratio); - using StillImageCallback = std::function)>; + using StillImageCallback = std::function)>; void renderStill(StillImageCallback callback); void triggerUpdate(Update = Update::Nothing); @@ -61,6 +61,7 @@ public: // ResourceLoader::Observer implementation. void onTileDataChanged() override; + void onResourceLoadingFailed(std::exception_ptr error) override; private: void updateTiles(); diff --git a/src/mbgl/map/resource_loader.cpp b/src/mbgl/map/resource_loader.cpp index 2be86dc5e..620b1b137 100644 --- a/src/mbgl/map/resource_loader.cpp +++ b/src/mbgl/map/resource_loader.cpp @@ -130,4 +130,20 @@ void ResourceLoader::emitTileDataChanged() { } } +void ResourceLoader::emitResourceLoadingFailed(std::exception_ptr error) { + assert(Environment::currentlyOn(ThreadType::Map)); + + try { + if (error) { + std::rethrow_exception(error); + } + } catch(const std::exception& e) { + Log::Error(Event::ResourceLoader, e.what()); + } + + if (observer_) { + observer_->onResourceLoadingFailed(error); + } +} + } diff --git a/src/mbgl/map/resource_loader.hpp b/src/mbgl/map/resource_loader.hpp index 379444135..fb05e67e1 100644 --- a/src/mbgl/map/resource_loader.hpp +++ b/src/mbgl/map/resource_loader.hpp @@ -32,6 +32,7 @@ public: virtual ~Observer() = default; virtual void onTileDataChanged() = 0; + virtual void onResourceLoadingFailed(std::exception_ptr error) = 0; }; ResourceLoader(); @@ -72,6 +73,7 @@ public: private: void emitTileDataChanged(); + void emitResourceLoadingFailed(std::exception_ptr error); bool shouldReparsePartialTiles_ = false; diff --git a/test/api/repeated_render.cpp b/test/api/repeated_render.cpp index ce7e6cbb0..f563b0007 100644 --- a/test/api/repeated_render.cpp +++ b/test/api/repeated_render.cpp @@ -28,7 +28,7 @@ TEST(API, RepeatedRender) { map.resize(128, 512, 1); map.setStyleJSON(style, "test/suite"); std::promise> promise; - map.renderStill([&promise](std::unique_ptr image) { + map.renderStill([&promise](std::exception_ptr, std::unique_ptr image) { promise.set_value(std::move(image)); }); auto result = promise.get_future().get(); @@ -42,7 +42,7 @@ TEST(API, RepeatedRender) { map.resize(512, 512, 2); map.setStyleJSON(style, "TEST_DATA/suite"); std::promise> promise; - map.renderStill([&promise](std::unique_ptr image) { + map.renderStill([&promise](std::exception_ptr, std::unique_ptr image) { promise.set_value(std::move(image)); }); auto result = promise.get_future().get(); diff --git a/test/headless/headless.cpp b/test/headless/headless.cpp index a02062dbd..8dfed0383 100644 --- a/test/headless/headless.cpp +++ b/test/headless/headless.cpp @@ -152,7 +152,7 @@ TEST_P(HeadlessTest, render) { map.setLatLngZoom(mbgl::LatLng(latitude, longitude), zoom); map.setBearing(bearing); - map.renderStill([&](std::unique_ptr image) { + map.renderStill([&](std::exception_ptr, std::unique_ptr image) { const std::string png = util::compress_png(image->width, image->height, image->pixels.get()); util::write_file("test/suite/tests/" + base + "/" + name + "/actual.png", png); promise.set_value();