From 12d350ec3c69b8d547eeb92ad2d818ca605308f7 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Thu, 13 Feb 2020 15:29:37 +0200 Subject: Revert "[core] Fix excessive onSpriteLoaded() notifications" This reverts commit 80cb05420a86ed53815cae7fb2cb3fddf07dd1d1. --- src/mbgl/sprite/sprite_loader.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mbgl/sprite/sprite_loader.cpp b/src/mbgl/sprite/sprite_loader.cpp index 6051de7ef4..56f7abd50b 100644 --- a/src/mbgl/sprite/sprite_loader.cpp +++ b/src/mbgl/sprite/sprite_loader.cpp @@ -58,9 +58,9 @@ void SpriteLoader::load(const std::string& url, FileSource& fileSource) { } else if (res.noContent) { loader->json = std::make_shared(); emitSpriteLoadedIfComplete(); - } else if (loader->json != res.data) { // They can be equal, see OnlineFileRequest::completed(). + } else { // Only trigger a sprite loaded event we got new data. - loader->json = std::move(res.data); + loader->json = res.data; emitSpriteLoadedIfComplete(); } }); @@ -73,8 +73,8 @@ void SpriteLoader::load(const std::string& url, FileSource& fileSource) { } else if (res.noContent) { loader->image = std::make_shared(); emitSpriteLoadedIfComplete(); - } else if (loader->image != res.data) { // They can be equal - see OnlineFileRequest::completed(). - loader->image = std::move(res.data); + } else { + loader->image = res.data; emitSpriteLoadedIfComplete(); } }); -- cgit v1.2.1 From 06f7951490982d777aae9f8144bfb8dcb508d234 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Thu, 13 Feb 2020 15:29:49 +0200 Subject: Revert "Add change log entry" This reverts commit d3535f1ca9f7c12b3c2290da3f347e4f95210425. --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bad7958a10..4bb86c8758 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,10 +32,6 @@ This change enables attaching images to the style with batches and avoids massive re-allocations. Thus, it improves UI performance especially at start-up time. - - [core] Fix excessive onSpriteLoaded() notifications ([#16196](https://github.com/mapbox/mapbox-gl-native/pull/16196)) - - The excessive `onSpriteLoaded()` notifications affected the render orchestration logic and could have significant negative performance impact. - ### 🧩 Architectural changes ##### ⚠️ Breaking changes -- cgit v1.2.1 From 89eab0530df08baf292d6d1260a3ae43019e3541 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Thu, 13 Feb 2020 11:56:13 +0200 Subject: [core] Set priorData from cache only if resource is useable In cases when cached resource is useable, yet don't have an expiration timestamp, we provided data to the requester from the cache and the same data was returned once 304 response was received from the network. --- platform/default/src/mbgl/storage/main_resource_loader.cpp | 6 +++++- src/mbgl/sprite/sprite_loader.cpp | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/platform/default/src/mbgl/storage/main_resource_loader.cpp b/platform/default/src/mbgl/storage/main_resource_loader.cpp index 9bdf09fa10..aa8d745170 100644 --- a/platform/default/src/mbgl/storage/main_resource_loader.cpp +++ b/platform/default/src/mbgl/storage/main_resource_loader.cpp @@ -81,13 +81,17 @@ public: callback(response); // Set the priority of existing resource to low if it's expired but usable. res.setPriority(Resource::Priority::Low); + } else { + // Set prior data only if it was not returned to the requester. + // Once we get 304 response from the network, we will forward response + // to the requester. + res.priorData = response.data; } // Copy response fields for cache control request res.priorModified = response.modified; res.priorExpires = response.expires; res.priorEtag = response.etag; - res.priorData = response.data; } tasks[req] = requestFromNetwork(res, std::move(tasks[req])); diff --git a/src/mbgl/sprite/sprite_loader.cpp b/src/mbgl/sprite/sprite_loader.cpp index 56f7abd50b..60bab2bf6e 100644 --- a/src/mbgl/sprite/sprite_loader.cpp +++ b/src/mbgl/sprite/sprite_loader.cpp @@ -60,7 +60,8 @@ void SpriteLoader::load(const std::string& url, FileSource& fileSource) { emitSpriteLoadedIfComplete(); } else { // Only trigger a sprite loaded event we got new data. - loader->json = res.data; + assert(loader->json != res.data); + loader->json = std::move(res.data); emitSpriteLoadedIfComplete(); } }); @@ -74,7 +75,8 @@ void SpriteLoader::load(const std::string& url, FileSource& fileSource) { loader->image = std::make_shared(); emitSpriteLoadedIfComplete(); } else { - loader->image = res.data; + assert(loader->image != res.data); + loader->image = std::move(res.data); emitSpriteLoadedIfComplete(); } }); -- cgit v1.2.1 From f42b5e94edd086d09d131b0e53aa72030d30afd7 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Thu, 13 Feb 2020 14:00:57 +0200 Subject: [core] Add unit test --- test/storage/main_resource_loader.test.cpp | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/storage/main_resource_loader.test.cpp b/test/storage/main_resource_loader.test.cpp index ee9211b064..b5245dbad8 100644 --- a/test/storage/main_resource_loader.test.cpp +++ b/test/storage/main_resource_loader.test.cpp @@ -8,6 +8,7 @@ #include #include #include +#include using namespace mbgl; @@ -749,3 +750,38 @@ TEST(MainResourceLoader, TEST_REQUIRES_SERVER(CachedResourceLowPriority)) { loop.run(); } + +TEST(MainResourceLoader, TEST_REQUIRES_SERVER(NoDoubleDispatch)) { + util::RunLoop loop; + MainResourceLoader fs(ResourceOptions{}); + + const Resource resource{Resource::Unknown, "http://127.0.0.1:3000/revalidate-same"}; + Response response; + response.data = std::make_shared("data"); + response.etag.emplace("snowfall"); + + std::unique_ptr req; + unsigned responseCount = 0u; + auto dbfs = FileSourceManager::get()->getFileSource(FileSourceType::Database, ResourceOptions{}); + dbfs->forward(resource, response, [&] { + req = fs.request(resource, [&](Response res) { + EXPECT_EQ(nullptr, res.error); + EXPECT_FALSE(bool(res.modified)); + EXPECT_TRUE(bool(res.etag)); + EXPECT_EQ("snowfall", *res.etag); + if (!res.notModified) { + ASSERT_TRUE(res.data.get()); + EXPECT_EQ("data", *res.data); + ++responseCount; + } + }); + }); + + util::Timer timer; + timer.start(Milliseconds(100), Duration::zero(), [&loop, &responseCount] { + EXPECT_EQ(1u, responseCount); + loop.stop(); + }); + + loop.run(); +} -- cgit v1.2.1 From ddc7930b2792ffe12e7d1d3e0a231b7e204e1ff5 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Thu, 13 Feb 2020 16:28:11 +0200 Subject: [core] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bb86c8758..cf0a476107 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,12 @@ - [core] Add support for using `within expression` with layout propery. ([#16194](https://github.com/mapbox/mapbox-gl-native/pull/16194)) +### 🐞 Bug fixes + +- [core] Don't provide multiple responses with the same data for 304 replies ([#16200](https://github.com/mapbox/mapbox-gl-native/pull/16200)) + + In cases when cached resource is useable, yet don't have an expiration timestamp, we provided data to the requester from the cache and the same data was returned once 304 response was received from the network. + ### 🏁 Performance improvements - [core] Loading images to style optimization ([#16187](https://github.com/mapbox/mapbox-gl-native/pull/16187)) -- cgit v1.2.1 From a4c4de28285a5abe1343fe5abf718adad2b9d354 Mon Sep 17 00:00:00 2001 From: Juha Alanen Date: Wed, 12 Feb 2020 12:34:30 +0200 Subject: [test] Fix failing tests on iOS --- test/fixtures/local_glyphs/ping_fang/expected.png | Bin 18174 -> 17731 bytes test/map/transform.test.cpp | 5 +++-- test/storage/offline_database.test.cpp | 8 ++++---- test/tile/vector_tile.test.cpp | 2 ++ test/util/tile_cover.test.cpp | 4 ++-- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/test/fixtures/local_glyphs/ping_fang/expected.png b/test/fixtures/local_glyphs/ping_fang/expected.png index 2ec62e1bc6..8c891a5232 100644 Binary files a/test/fixtures/local_glyphs/ping_fang/expected.png and b/test/fixtures/local_glyphs/ping_fang/expected.png differ diff --git a/test/map/transform.test.cpp b/test/map/transform.test.cpp index 95fb744206..02ecbfbee4 100644 --- a/test/map/transform.test.cpp +++ b/test/map/transform.test.cpp @@ -621,7 +621,8 @@ TEST(Transform, LatLngBounds) { } transform.jumpTo(CameraOptions().withCenter(sanFrancisco)); - ASSERT_EQ(transform.getLatLng(), sanFrancisco); + ASSERT_NEAR(transform.getLatLng().latitude(), sanFrancisco.latitude(), 1e-8); + ASSERT_NEAR(transform.getLatLng().longitude(), sanFrancisco.longitude(), 1e-8); // Single location. transform.setLatLngBounds(LatLngBounds::singleton(sanFrancisco)); @@ -655,7 +656,7 @@ TEST(Transform, LatLngBounds) { // β””β”€β”€β”€β”΄β”€β”€β”€β”Έβ”€β”€β”€β”΄β”€β”€β”€β”Έβ”€β”€β”€β”΄β”€β”€β”€β”˜ transform.setLatLngBounds(LatLngBounds::hull({ -90.0, 0.0 }, { 90.0, 180.0 })); transform.jumpTo(CameraOptions().withCenter(sanFrancisco)); - ASSERT_EQ(transform.getLatLng().latitude(), sanFrancisco.latitude()); + ASSERT_NEAR(transform.getLatLng().latitude(), sanFrancisco.latitude(), 1e-8); ASSERT_EQ(transform.getLatLng().longitude(), 0.0); // -1 | 0 | +1 diff --git a/test/storage/offline_database.test.cpp b/test/storage/offline_database.test.cpp index f988457dac..f344151297 100644 --- a/test/storage/offline_database.test.cpp +++ b/test/storage/offline_database.test.cpp @@ -779,7 +779,7 @@ TEST(OfflineDatabase, MapboxTileLimitExceeded) { db.put(ambientTile, response); }; - auto insertRegionTile = [&](int64_t regionID, unsigned i) { + auto insertRegionTile = [&](int64_t regionID, uint64_t i) { const Resource tile = Resource::tile("mapbox://region_tile_" + std::to_string(i), 1, 0, 0, 0, Tileset::Scheme::XYZ); db.putRegionResource(regionID, tile, response); }; @@ -801,14 +801,14 @@ TEST(OfflineDatabase, MapboxTileLimitExceeded) { ASSERT_EQ(db.getOfflineMapboxTileCount(), 0); // Fine because this region is under the tile limit. - for (unsigned i = 0; i < limit - 10; ++i) { + for (uint64_t i = 0; i < limit - 10; ++i) { insertRegionTile(region1->getID(), i); } ASSERT_EQ(db.getOfflineMapboxTileCount(), limit - 10); // Fine because this region + the previous is at the limit. - for (unsigned i = limit; i < limit + 10; ++i) { + for (uint64_t i = limit; i < limit + 10; ++i) { insertRegionTile(region2->getID(), i); } @@ -848,7 +848,7 @@ TEST(OfflineDatabase, MapboxTileLimitExceeded) { // 10, which would blow up the limit if it wasn't // for the fact that tile 60 is already on the // database and will not count. - for (unsigned i = limit; i < limit + 10; ++i) { + for (uint64_t i = limit; i < limit + 10; ++i) { insertRegionTile(region1->getID(), i); } diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp index d282c874ef..b89a572f7f 100644 --- a/test/tile/vector_tile.test.cpp +++ b/test/tile/vector_tile.test.cpp @@ -91,6 +91,8 @@ TEST(VectorTileData, ParseResults) { ASSERT_TRUE(false) << "should throw: feature index is out of range."; } catch (const std::out_of_range&) { ASSERT_TRUE(true); + } catch (...) { // needed for iOS when MBGL_WITH_RTTI=OFF + ASSERT_TRUE(true); } std::unique_ptr feature = layer->getFeature(0u); diff --git a/test/util/tile_cover.test.cpp b/test/util/tile_cover.test.cpp index af9f0c4884..ba39bfa61b 100644 --- a/test/util/tile_cover.test.cpp +++ b/test/util/tile_cover.test.cpp @@ -365,7 +365,7 @@ TEST(TileCount, BoundsCrossingAntimeridian) { TEST(TileCover, DISABLED_FuzzPoly) { while(true) { - std::srand (time(nullptr)); + std::srand(static_cast(time(nullptr))); std::size_t len = std::rand() % 10000 + 3; Polygon polygon; @@ -393,7 +393,7 @@ TEST(TileCover, DISABLED_FuzzPoly) { TEST(TileCover, DISABLED_FuzzLine) { while(true) { - std::srand (time(nullptr)); + std::srand(static_cast(time(nullptr))); std::size_t len = std::rand() % 10000 + 3; MultiLineString mls; -- cgit v1.2.1 From 632c5f9d4c42a6e408c0565e34b2d1bd428ff018 Mon Sep 17 00:00:00 2001 From: Juha Alanen Date: Fri, 31 Jan 2020 11:52:12 +0200 Subject: [test] Add iOS unit test runner --- platform/ios/ios.cmake | 94 ++++++++++++++++++++++ test/CMakeLists.txt | 18 +++++ test/include/mbgl/test/util.hpp | 17 ++-- test/ios/AppDelegate.h | 7 ++ test/ios/AppDelegate.m | 38 +++++++++ test/ios/Gemfile | 3 + test/ios/Info.plist | 62 ++++++++++++++ test/ios/LaunchScreen.storyboard | 27 +++++++ test/ios/Main.storyboard | 27 +++++++ test/ios/README.md | 7 ++ ...nitTestsApp_iphoneos13.2-arm64e-debug.xctestrun | 68 ++++++++++++++++ ...tTestsApp_iphoneos13.2-arm64e-release.xctestrun | 68 ++++++++++++++++ test/ios/ViewController.h | 6 ++ test/ios/ViewController.m | 22 +++++ .../codesigning/UnitTestsApp.app.xcent.template | 16 ++++ .../UnitTestsAppTests.xctest.xcent.template | 16 ++++ .../XCTAutomationSupport.framework.xcent.template | 16 ++++ .../codesigning/XCTest.framework.xcent.template | 16 ++++ test/ios/codesigning/codesign_all.sh | 8 ++ test/ios/codesigning/generate-entitlements.swift | 40 +++++++++ .../libXCTestSwiftSupport.dylib.xcent.template | 16 ++++ test/ios/fastlane/Appfile | 3 + test/ios/fastlane/Matchfile | 5 ++ test/ios/iosTestRunner.h | 9 +++ test/ios/iosTestRunner.mm | 82 +++++++++++++++++++ test/ios/ios_test_runner.cpp | 31 +++++++ test/ios/ios_test_runner.hpp | 14 ++++ test/ios/main.m | 9 +++ test/ios/tests/Info.plist | 22 +++++ test/ios/tests/Tests.m | 37 +++++++++ 30 files changed, 793 insertions(+), 11 deletions(-) create mode 100644 test/ios/AppDelegate.h create mode 100644 test/ios/AppDelegate.m create mode 100644 test/ios/Gemfile create mode 100644 test/ios/Info.plist create mode 100644 test/ios/LaunchScreen.storyboard create mode 100644 test/ios/Main.storyboard create mode 100644 test/ios/README.md create mode 100644 test/ios/UnitTestsApp_iphoneos13.2-arm64e-debug.xctestrun create mode 100644 test/ios/UnitTestsApp_iphoneos13.2-arm64e-release.xctestrun create mode 100644 test/ios/ViewController.h create mode 100644 test/ios/ViewController.m create mode 100644 test/ios/codesigning/UnitTestsApp.app.xcent.template create mode 100644 test/ios/codesigning/UnitTestsAppTests.xctest.xcent.template create mode 100644 test/ios/codesigning/XCTAutomationSupport.framework.xcent.template create mode 100644 test/ios/codesigning/XCTest.framework.xcent.template create mode 100755 test/ios/codesigning/codesign_all.sh create mode 100755 test/ios/codesigning/generate-entitlements.swift create mode 100644 test/ios/codesigning/libXCTestSwiftSupport.dylib.xcent.template create mode 100644 test/ios/fastlane/Appfile create mode 100644 test/ios/fastlane/Matchfile create mode 100644 test/ios/iosTestRunner.h create mode 100644 test/ios/iosTestRunner.mm create mode 100644 test/ios/ios_test_runner.cpp create mode 100644 test/ios/ios_test_runner.hpp create mode 100644 test/ios/main.m create mode 100644 test/ios/tests/Info.plist create mode 100644 test/ios/tests/Tests.m diff --git a/platform/ios/ios.cmake b/platform/ios/ios.cmake index aa22a376f8..85b22afcc0 100644 --- a/platform/ios/ios.cmake +++ b/platform/ios/ios.cmake @@ -191,4 +191,98 @@ if(MBGL_IOS_RENDER_TEST) set_target_properties(RenderTestAppTests PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/render-test/ios/tests/Info.plist) endif() +if(MBGL_IOS_UNIT_TEST) + execute_process(COMMAND ditto ${PROJECT_SOURCE_DIR}/test/fixtures ${CMAKE_CURRENT_BINARY_DIR}/test-data/test/fixtures) + execute_process( + COMMAND + ditto ${PROJECT_SOURCE_DIR}/mapbox-gl-js/src/style-spec/reference + ${CMAKE_CURRENT_BINARY_DIR}/test-data/mapbox-gl-js/src/style-spec/reference + ) + + set( + RESOURCES + ${PROJECT_SOURCE_DIR}/test/ios/Main.storyboard + ${PROJECT_SOURCE_DIR}/test/ios/LaunchScreen.storyboard + ${CMAKE_CURRENT_BINARY_DIR}/test-data + ) + + add_executable( + UnitTestsApp + ${PROJECT_SOURCE_DIR}/test/ios/ios_test_runner.hpp + ${PROJECT_SOURCE_DIR}/test/ios/ios_test_runner.cpp + ${PROJECT_SOURCE_DIR}/test/ios/AppDelegate.h + ${PROJECT_SOURCE_DIR}/test/ios/AppDelegate.m + ${PROJECT_SOURCE_DIR}/test/ios/ViewController.h + ${PROJECT_SOURCE_DIR}/test/ios/ViewController.m + ${PROJECT_SOURCE_DIR}/test/ios/iosTestRunner.h + ${PROJECT_SOURCE_DIR}/test/ios/iosTestRunner.mm + ${PROJECT_SOURCE_DIR}/test/ios/main.m + ${RESOURCES} + ) + initialize_ios_target(UnitTestsApp) + + set_target_properties( + UnitTestsApp + PROPERTIES + MACOSX_BUNDLE + TRUE + MACOSX_BUNDLE_IDENTIFIER + com.mapbox.UnitTestsApp + MACOSX_BUNDLE_INFO_PLIST + ${PROJECT_SOURCE_DIR}/test/ios/Info.plist + RESOURCE + "${RESOURCES}" + ) + + target_include_directories( + UnitTestsApp + PUBLIC {MBGL_ROOT}/test/include ${PROJECT_SOURCE_DIR}/include + ) + + target_include_directories( + UnitTestsApp + PUBLIC ${PROJECT_SOURCE_DIR}/test/ios + ) + + target_link_libraries( + UnitTestsApp + PRIVATE + "-framework CoreGraphics" + "-framework CoreLocation" + "-framework Foundation" + "-framework OpenGLES" + "-framework QuartzCore" + "-framework UIKit" + mbgl-compiler-options + -Wl,-force_load + mbgl-test + ) + + set_target_properties(UnitTestsApp PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "") + set_target_properties(UnitTestsApp PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") + + find_package(XCTest REQUIRED) + + xctest_add_bundle(UnitTestsAppTests UnitTestsApp ${PROJECT_SOURCE_DIR}/test/ios/tests/Tests.m) + + set_target_properties( + UnitTestsAppTests + PROPERTIES + XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET + "${IOS_DEPLOYMENT_TARGET}" + XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH + $<$:YES> + ) + + target_include_directories( + UnitTestsAppTests + PUBLIC ${PROJECT_SOURCE_DIR}/test/ios + ) + + xctest_add_test(XCTest.UnitTestsApp UnitTestsAppTests) + + set_target_properties(UnitTestsAppTests PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/test/ios/tests/Info.plist) + set_target_properties(UnitTestsAppTests PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "") + set_target_properties(UnitTestsAppTests PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") +endif() unset(IOS_DEPLOYMENT_TARGET CACHE) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index dcde7cd21a..a9ae0ac874 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -134,6 +134,12 @@ else() COMPILE_FLAGS -Wno-shadow ) + set_source_files_properties( + ${PROJECT_SOURCE_DIR}/test/src/mbgl/test/http_server.cpp + PROPERTIES + COMPILE_OPTIONS + $<$:-Wno-shorten-64-to-32> + ) target_include_directories( mbgl-test PRIVATE ${PROJECT_SOURCE_DIR}/vendor/cpp-httplib @@ -167,6 +173,18 @@ target_include_directories( include(${PROJECT_SOURCE_DIR}/vendor/googletest.cmake) +if(CMAKE_SYSTEM_NAME STREQUAL iOS) + set_target_properties(mbgl-vendor-googletest PROPERTIES XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${IOS_DEPLOYMENT_TARGET}") + set_target_properties(mbgl-vendor-googletest PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "YES") + set_target_properties(mbgl-vendor-googletest PROPERTIES XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE bitcode) + set_target_properties(mbgl-vendor-googletest PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH $<$:YES>) + + set_target_properties(mbgl-test PROPERTIES XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${IOS_DEPLOYMENT_TARGET}") + set_target_properties(mbgl-test PROPERTIES XCODE_ATTRIBUTE_ENABLE_BITCODE "YES") + set_target_properties(mbgl-test PROPERTIES XCODE_ATTRIBUTE_BITCODE_GENERATION_MODE bitcode) + set_target_properties(mbgl-test PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH $<$:YES>) +endif() + # Needed for testing private classes get_target_property(MBGL_CORE_PRIVATE_LIBRARIES mbgl-core LINK_LIBRARIES) diff --git a/test/include/mbgl/test/util.hpp b/test/include/mbgl/test/util.hpp index 959b3e646f..a8b1d1b2c6 100644 --- a/test/include/mbgl/test/util.hpp +++ b/test/include/mbgl/test/util.hpp @@ -4,17 +4,12 @@ #include #endif -#if ANDROID - #define TEST_READ_ONLY 0 -#elif TARGET_OS_IOS - #define TEST_READ_ONLY 1 - #undef TEST_HAS_SERVER - #define TEST_HAS_SERVER 0 -#else - #define TEST_READ_ONLY 0 - #ifndef TEST_HAS_SERVER - #define TEST_HAS_SERVER 1 - #endif +#define TEST_READ_ONLY 0 + +#if !ANDROID +#ifndef TEST_HAS_SERVER +#define TEST_HAS_SERVER 1 +#endif #endif #if TARGET_OS_SIMULATOR diff --git a/test/ios/AppDelegate.h b/test/ios/AppDelegate.h new file mode 100644 index 0000000000..134c8063dc --- /dev/null +++ b/test/ios/AppDelegate.h @@ -0,0 +1,7 @@ +#import // UIApplicationDelegate + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end \ No newline at end of file diff --git a/test/ios/AppDelegate.m b/test/ios/AppDelegate.m new file mode 100644 index 0000000000..874d18de2a --- /dev/null +++ b/test/ios/AppDelegate.m @@ -0,0 +1,38 @@ +#import "AppDelegate.h" + +@interface AppDelegate() + +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Insert code here to initialize your application + NSLog(@"didFinishLaunchingWithOptions"); + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + + +@end diff --git a/test/ios/Gemfile b/test/ios/Gemfile new file mode 100644 index 0000000000..adc90d98cf --- /dev/null +++ b/test/ios/Gemfile @@ -0,0 +1,3 @@ +source "https://rubygems.org" + +gem "fastlane" \ No newline at end of file diff --git a/test/ios/Info.plist b/test/ios/Info.plist new file mode 100644 index 0000000000..c53d0d06e9 --- /dev/null +++ b/test/ios/Info.plist @@ -0,0 +1,62 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + UnitTestsApp + CFBundleIdentifier + com.mapbox.UnitTestsApp + CFBundleGetInfoString + com.mapbox.UnitTestsApp + CFBundleInfoDictionaryVersion + 1.0 + CFBundleLongVersionString + 1.0 + CFBundleName + com.mapbox.UnitTestsApp + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + MBGL + CFBundleVersion + 7877 + CSResourcesFileMapped + + NSHumanReadableCopyright + Β© 2014–2020 Mapbox + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIBackgroundModes + + fetch + remote-notification + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + + \ No newline at end of file diff --git a/test/ios/LaunchScreen.storyboard b/test/ios/LaunchScreen.storyboard new file mode 100644 index 0000000000..c9b7564332 --- /dev/null +++ b/test/ios/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/ios/Main.storyboard b/test/ios/Main.storyboard new file mode 100644 index 0000000000..34d4c7e2ec --- /dev/null +++ b/test/ios/Main.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/ios/README.md b/test/ios/README.md new file mode 100644 index 0000000000..5b0d1f6a08 --- /dev/null +++ b/test/ios/README.md @@ -0,0 +1,7 @@ +# iOS UnitTestsRunner App + +This is a blank single-view-controller iOS app, linked against to a C++ static libraries, plus a a simple unit xctest. We use CMake to create an Xcode-friendly out-of-source build system. In another word, the build system is maintained by `CMakeLists` file,instead of a configured `.xcodeproj` file. + +This CMake project can build the executable UnitTestsApp which is linked to the static C++ library 'mbgl-test'. CMakeLists.txt files are the only build configuration kept in source control. This is in contrast to committing the `.xcodeproj` directory which includes the backing XML, which is nonsensically hard to edit by hand. + +The test instantiates ObjC object of class `IosTestRunner` from the app, the class will instantiates a C++ object from the linked library `mbgl-test` and calls running unit test function on it. It subsequently deletes the C++ object pointer. In the end, the test will check the existence of test report, which is an xml file that attach to xctest result. diff --git a/test/ios/UnitTestsApp_iphoneos13.2-arm64e-debug.xctestrun b/test/ios/UnitTestsApp_iphoneos13.2-arm64e-debug.xctestrun new file mode 100644 index 0000000000..b6b7a9d1b0 --- /dev/null +++ b/test/ios/UnitTestsApp_iphoneos13.2-arm64e-debug.xctestrun @@ -0,0 +1,68 @@ + + + + + UnitTestsAppTests + + BlueprintName + UnitTestsAppTests + BundleIdentifiersForCrashReportEmphasis + + com.mapbox.UnitTestsApp + com.mapbox.UnitTestsAppTests + + CommandLineArguments + + DependentProductPaths + + __TESTROOT__/Debug-iphoneos/UnitTestsApp.app + __TESTROOT__/Debug-iphoneos/UnitTestsApp.app/PlugIns/UnitTestsAppTests.xctest + + EnvironmentVariables + + OS_ACTIVITY_DT_MODE + YES + SQLITE_ENABLE_THREAD_ASSERTIONS + 1 + + IsAppHostedTestBundle + + ProductModuleName + UnitTestsAppTests + RunOrder + 0 + SystemAttachmentLifetime + deleteOnSuccess + TestBundlePath + __TESTHOST__/PlugIns/UnitTestsAppTests.xctest + TestHostBundleIdentifier + com.mapbox.UnitTestsApp + TestHostPath + __TESTROOT__/Debug-iphoneos/UnitTestsApp.app + TestLanguage + + TestRegion + + TestingEnvironmentVariables + + DYLD_FALLBACK_FRAMEWORK_PATH + + DYLD_INSERT_LIBRARIES + __PLATFORMS__/iPhoneOS.platform/Developer/usr/lib/libXCTestBundleInject.dylib + XCInjectBundleInto + unused + + ToolchainsSettingValue + + UITargetAppCommandLineArguments + + UserAttachmentLifetime + deleteOnSuccess + + __xctestrun_metadata__ + + FormatVersion + 1 + + + diff --git a/test/ios/UnitTestsApp_iphoneos13.2-arm64e-release.xctestrun b/test/ios/UnitTestsApp_iphoneos13.2-arm64e-release.xctestrun new file mode 100644 index 0000000000..02038a4417 --- /dev/null +++ b/test/ios/UnitTestsApp_iphoneos13.2-arm64e-release.xctestrun @@ -0,0 +1,68 @@ + + + + + UnitTestsAppTests + + BlueprintName + UnitTestsAppTests + BundleIdentifiersForCrashReportEmphasis + + com.mapbox.UnitTestsApp + com.mapbox.UnitTestsAppTests + + CommandLineArguments + + DependentProductPaths + + __TESTROOT__/Release-iphoneos/UnitTestsApp.app + __TESTROOT__/Release-iphoneos/UnitTestsApp.app/PlugIns/UnitTestsAppTests.xctest + + EnvironmentVariables + + OS_ACTIVITY_DT_MODE + YES + SQLITE_ENABLE_THREAD_ASSERTIONS + 1 + + IsAppHostedTestBundle + + ProductModuleName + UnitTestsAppTests + RunOrder + 0 + SystemAttachmentLifetime + deleteOnSuccess + TestBundlePath + __TESTHOST__/PlugIns/UnitTestsAppTests.xctest + TestHostBundleIdentifier + com.mapbox.UnitTestsApp + TestHostPath + __TESTROOT__/Release-iphoneos/UnitTestsApp.app + TestLanguage + + TestRegion + + TestingEnvironmentVariables + + DYLD_FALLBACK_FRAMEWORK_PATH + + DYLD_INSERT_LIBRARIES + __PLATFORMS__/iPhoneOS.platform/Developer/usr/lib/libXCTestBundleInject.dylib + XCInjectBundleInto + unused + + ToolchainsSettingValue + + UITargetAppCommandLineArguments + + UserAttachmentLifetime + deleteOnSuccess + + __xctestrun_metadata__ + + FormatVersion + 1 + + + diff --git a/test/ios/ViewController.h b/test/ios/ViewController.h new file mode 100644 index 0000000000..9c7dfc57ec --- /dev/null +++ b/test/ios/ViewController.h @@ -0,0 +1,6 @@ +#import + +@interface ViewController : UIViewController + +@end + diff --git a/test/ios/ViewController.m b/test/ios/ViewController.m new file mode 100644 index 0000000000..e9c526122a --- /dev/null +++ b/test/ios/ViewController.m @@ -0,0 +1,22 @@ +#import "ViewController.h" +#import "iosTestRunner.h" + +@interface ViewController () +{ + IosTestRunner* i; +} +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; +// In order to run test runner with app itself instead of with unit test, comment out the following line. +// i = [[IosTestRunner alloc]init]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +@end diff --git a/test/ios/codesigning/UnitTestsApp.app.xcent.template b/test/ios/codesigning/UnitTestsApp.app.xcent.template new file mode 100644 index 0000000000..a851541766 --- /dev/null +++ b/test/ios/codesigning/UnitTestsApp.app.xcent.template @@ -0,0 +1,16 @@ + + + + + application-identifier + $TEAM_ID.com.mapbox.UnitTestsApp + com.apple.developer.team-identifier + $TEAM_ID + get-task-allow + + keychain-access-groups + + $TEAM_ID.com.mapbox.UnitTestsApp + + + \ No newline at end of file diff --git a/test/ios/codesigning/UnitTestsAppTests.xctest.xcent.template b/test/ios/codesigning/UnitTestsAppTests.xctest.xcent.template new file mode 100644 index 0000000000..72b2dbbb9d --- /dev/null +++ b/test/ios/codesigning/UnitTestsAppTests.xctest.xcent.template @@ -0,0 +1,16 @@ + + + + + application-identifier + $TEAM_ID.com.mapbox.UnitTestsAppTests + com.apple.developer.team-identifier + $TEAM_ID + get-task-allow + + keychain-access-groups + + $TEAM_ID.com.mapbox.UnitTestsAppTests + + + \ No newline at end of file diff --git a/test/ios/codesigning/XCTAutomationSupport.framework.xcent.template b/test/ios/codesigning/XCTAutomationSupport.framework.xcent.template new file mode 100644 index 0000000000..72b2dbbb9d --- /dev/null +++ b/test/ios/codesigning/XCTAutomationSupport.framework.xcent.template @@ -0,0 +1,16 @@ + + + + + application-identifier + $TEAM_ID.com.mapbox.UnitTestsAppTests + com.apple.developer.team-identifier + $TEAM_ID + get-task-allow + + keychain-access-groups + + $TEAM_ID.com.mapbox.UnitTestsAppTests + + + \ No newline at end of file diff --git a/test/ios/codesigning/XCTest.framework.xcent.template b/test/ios/codesigning/XCTest.framework.xcent.template new file mode 100644 index 0000000000..72b2dbbb9d --- /dev/null +++ b/test/ios/codesigning/XCTest.framework.xcent.template @@ -0,0 +1,16 @@ + + + + + application-identifier + $TEAM_ID.com.mapbox.UnitTestsAppTests + com.apple.developer.team-identifier + $TEAM_ID + get-task-allow + + keychain-access-groups + + $TEAM_ID.com.mapbox.UnitTestsAppTests + + + \ No newline at end of file diff --git a/test/ios/codesigning/codesign_all.sh b/test/ios/codesigning/codesign_all.sh new file mode 100755 index 0000000000..1a6007ea94 --- /dev/null +++ b/test/ios/codesigning/codesign_all.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +codesign --force --sign $CODESIGNIDENTITY --entitlements ../codesigning/UnitTestsApp.app.xcent --timestamp=none ./Release-iphoneos/UnitTestsApp.app +codesign --force --sign $CODESIGNIDENTITY --deep --preserve-metadata=identifier,entitlements,flags --timestamp=none ./Release-iphoneos/UnitTestsApp.app/Frameworks/libXCTestSwiftSupport.dylib +codesign --force --sign $CODESIGNIDENTITY --deep --preserve-metadata=identifier,entitlements,flags --timestamp=none ./Release-iphoneos/UnitTestsApp.app/Frameworks/libXCTestBundleInject.dylib +codesign --force --sign $CODESIGNIDENTITY --deep --preserve-metadata=identifier,entitlements,flags --timestamp=none ./Release-iphoneos/UnitTestsApp.app/Frameworks/XCTAutomationSupport.framework +codesign --force --sign $CODESIGNIDENTITY --deep --preserve-metadata=identifier,entitlements,flags --timestamp=none ./Release-iphoneos/UnitTestsApp.app/Frameworks/XCTest.framework +codesign --force --sign $CODESIGNIDENTITY --deep --entitlements ../codesigning/UnitTestsAppTests.xctest.xcent --timestamp=none ./Release-iphoneos/UnitTestsApp.app/PlugIns/UnitTestsAppTests.xctest diff --git a/test/ios/codesigning/generate-entitlements.swift b/test/ios/codesigning/generate-entitlements.swift new file mode 100755 index 0000000000..83834483bf --- /dev/null +++ b/test/ios/codesigning/generate-entitlements.swift @@ -0,0 +1,40 @@ +#!/usr/bin/swift + +/// Generates Entitlement files .xcent for codesigning, containing the correct team id +import Swift +import Foundation + +let fileManager = FileManager.default + +let contentsOfCurrentWorkingDirectory = try FileManager.default.contentsOfDirectory(at: URL(fileURLWithPath: "./codesigning/"), includingPropertiesForKeys: nil, options: []) + +guard let rawTeamIdEnv = getenv("IOS_DEVELOPMENT_TEAM") else { + print("Please add a IOS_DEVELOPMENT_TEAM environment variable.") + exit(1) +} + +let teamId2 = String(utf8String: rawTeamIdEnv) + +for file in contentsOfCurrentWorkingDirectory { + if (file.pathExtension == "template") { + var content = "" + do { + content = try String(contentsOf: file, encoding: .utf8) + } + catch { + print("Error reading xcent file: \(error).") + } + + content = content.replacingOccurrences(of: "$TEAM_ID", with: teamId2!) + + var targetFile = file + targetFile.deletePathExtension() + do { + try content.write(to: targetFile, atomically: false, encoding: .utf8) + print("Entitlement " + targetFile.absoluteString + " generated.") + } + catch { + print("Error writing xcent file: \(error).") + } + } +} \ No newline at end of file diff --git a/test/ios/codesigning/libXCTestSwiftSupport.dylib.xcent.template b/test/ios/codesigning/libXCTestSwiftSupport.dylib.xcent.template new file mode 100644 index 0000000000..72b2dbbb9d --- /dev/null +++ b/test/ios/codesigning/libXCTestSwiftSupport.dylib.xcent.template @@ -0,0 +1,16 @@ + + + + + application-identifier + $TEAM_ID.com.mapbox.UnitTestsAppTests + com.apple.developer.team-identifier + $TEAM_ID + get-task-allow + + keychain-access-groups + + $TEAM_ID.com.mapbox.UnitTestsAppTests + + + \ No newline at end of file diff --git a/test/ios/fastlane/Appfile b/test/ios/fastlane/Appfile new file mode 100644 index 0000000000..f9e7e1e7c1 --- /dev/null +++ b/test/ios/fastlane/Appfile @@ -0,0 +1,3 @@ +app_identifier("com.mapbox.UnitTestsApp") # The bundle identifier of your app +apple_id ENV['MAPBOX_APPLE_ID'] +team_id ENV['MAPBOX_APPLE_TEAM_ID'] # Developer Portal Team ID \ No newline at end of file diff --git a/test/ios/fastlane/Matchfile b/test/ios/fastlane/Matchfile new file mode 100644 index 0000000000..2a815bfc8e --- /dev/null +++ b/test/ios/fastlane/Matchfile @@ -0,0 +1,5 @@ +git_url("git@github.com:mapbox/apple-certificates.git") +type("development") # The default type, can be: appstore, adhoc, enterprise or development +app_identifier(["com.mapbox.UnitTestsApp", "com.mapbox.UnitTestsAppTests"]) +username ENV['MAPBOX_APPLE_ID'] +keychain_name("fastlane_keychain") \ No newline at end of file diff --git a/test/ios/iosTestRunner.h b/test/ios/iosTestRunner.h new file mode 100644 index 0000000000..dcbb77e9d4 --- /dev/null +++ b/test/ios/iosTestRunner.h @@ -0,0 +1,9 @@ +#import + +__attribute__((visibility ("default"))) +@interface IosTestRunner : NSObject + +- (NSString*) getResultPath; +- (BOOL) getTestStatus; + +@end diff --git a/test/ios/iosTestRunner.mm b/test/ios/iosTestRunner.mm new file mode 100644 index 0000000000..383b9036ec --- /dev/null +++ b/test/ios/iosTestRunner.mm @@ -0,0 +1,82 @@ +#import "iosTestRunner.h" + +#include "ios_test_runner.hpp" + +#include + +@interface IosTestRunner () + +@property (nullable) TestRunner* runner; + +@property (copy, nullable) NSString *resultPath; + +@property BOOL testStatus; + +@end + +@implementation IosTestRunner + +-(instancetype)init +{ + self = [super init]; + if (self) { + self.testStatus = NO; + self.runner = new TestRunner(); + NSError *error; + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *bundleRoot = [[NSBundle mainBundle] bundlePath]; + NSArray *bundleContents = [fileManager contentsOfDirectoryAtPath: bundleRoot error: &error]; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDir = [paths objectAtIndex: 0]; + + for (uint32_t i = 0; i < bundleContents.count; i++) { + NSString *dirName = [bundleContents objectAtIndex: i]; + if ([dirName isEqualToString:@"test-data"]) { + NSString *destinationPath = [documentsDir stringByAppendingPathComponent: dirName]; + BOOL success = [fileManager fileExistsAtPath: destinationPath]; + if (success) { + [fileManager removeItemAtPath:destinationPath error:NULL]; + } + + success = [fileManager fileExistsAtPath: destinationPath]; + if (!success) { + NSString *copyDirPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: dirName]; + success = [fileManager copyItemAtPath: copyDirPath toPath: destinationPath error: &error]; + + if (!success) { + NSLog(@"Failed to copy file '%@'", dirName); + NSAssert1(0, @"Failed to copy file, error '%@'", [error localizedDescription]); + } else { + NSLog(@"File '%@' copied OK", dirName); + } + } else { + NSLog(@"Failed to remove file '%@'", dirName); + NSAssert1(0, @"Failed to remove file, error '%@'", [error localizedDescription]); + } + break; + } + } + std::string basePath = std::string([documentsDir UTF8String]) + std::string("/test-data"); + self.testStatus = self.runner->startTest(basePath) ? YES : NO; + self.resultPath = [documentsDir stringByAppendingPathComponent:@"/test-data/test/results.xml"]; + + BOOL fileFound = [fileManager fileExistsAtPath: self.resultPath]; + if (fileFound == NO) { + NSLog(@"Test result file '%@' does not exist", self.resultPath); + self.testStatus = NO; + } + + delete self.runner; + self.runner = nullptr; + } + return self; +} + +- (NSString*) getResultPath { + return self.resultPath; +} + +- (BOOL) getTestStatus { + return self.testStatus; +} +@end diff --git a/test/ios/ios_test_runner.cpp b/test/ios/ios_test_runner.cpp new file mode 100644 index 0000000000..293a2955b5 --- /dev/null +++ b/test/ios/ios_test_runner.cpp @@ -0,0 +1,31 @@ +#include "ios_test_runner.hpp" + +#include + +#include + +#include +#include + +#define EXPORT __attribute__((visibility("default"))) + +EXPORT +bool TestRunner::startTest(const std::string& basePath) { + std::vector arguments = {"mbgl-test-runner", "--gtest_output=xml:" + basePath + "/test/results.xml"}; + std::vector argv; + for (const auto& arg : arguments) { + argv.push_back(const_cast(arg.data())); + } + argv.push_back(nullptr); + + if (chdir(basePath.c_str())) { + mbgl::Log::Error(mbgl::Event::General, "Failed to change the directory to " + basePath); + return false; + } + + mbgl::Log::Info(mbgl::Event::General, "Start TestRunner"); + int status = mbgl::runTests(static_cast(argv.size()), argv.data()); + mbgl::Log::Info(mbgl::Event::General, "TestRunner finished with status: '%d'", status); + + return status == 0; +} diff --git a/test/ios/ios_test_runner.hpp b/test/ios/ios_test_runner.hpp new file mode 100644 index 0000000000..3edae22828 --- /dev/null +++ b/test/ios/ios_test_runner.hpp @@ -0,0 +1,14 @@ +#ifndef ios_test_runner_hpp +#define ios_test_runner_hpp + +#include + +class TestRunner { +public: + TestRunner() = default; + ~TestRunner() = default; + + bool startTest(const std::string& basePath); +}; + +#endif /* ios_test_runner_hpp */ diff --git a/test/ios/main.m b/test/ios/main.m new file mode 100644 index 0000000000..f813c8fea9 --- /dev/null +++ b/test/ios/main.m @@ -0,0 +1,9 @@ +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/test/ios/tests/Info.plist b/test/ios/tests/Info.plist new file mode 100644 index 0000000000..ba6b34e5b6 --- /dev/null +++ b/test/ios/tests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + UnitTestsAppTests + CFBundleIdentifier + com.mapbox.UnitTestsAppTests + CFBundleInfoDictionaryVersion + 1.0 + CFBundleName + UnitTestsAppTests + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/test/ios/tests/Tests.m b/test/ios/tests/Tests.m new file mode 100644 index 0000000000..4c2131d61c --- /dev/null +++ b/test/ios/tests/Tests.m @@ -0,0 +1,37 @@ +#import +#import "iosTestRunner.h" +@interface Tests : XCTestCase + +@end + +@implementation Tests + +- (void)setUp { + [super setUp]; +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testStartUnitTestRunner { + IosTestRunner* runner = [[IosTestRunner alloc] init]; + XCTAssert(runner, @"IOSTestRunner is not initialized correctly"); + + NSString* testResult = [runner getResultPath]; + XCTAssert(testResult, @"IOSTestRunner did not produce a test result file"); + + NSFileManager *fileManager = [NSFileManager defaultManager]; + BOOL fileFound = [fileManager fileExistsAtPath: testResult]; + XCTAssert(fileFound, @"Test result file '%@' does not exit", testResult); + NSURL *resultURL = [NSURL fileURLWithPath:testResult]; + XCTAttachment *attachment1URL = [XCTAttachment attachmentWithContentsOfFileAtURL: resultURL]; + XCTAssert(attachment1URL, @"Failed to attach test result '%@'", testResult); + attachment1URL.lifetime = XCTAttachmentLifetimeKeepAlways; + [self addAttachment:attachment1URL]; + + BOOL success = [runner getTestStatus]; + XCTAssert(success, @"IOSTestRunner reports error because some of the tests are not passed, please check the test report"); +} + +@end -- cgit v1.2.1 From af7428254b0c65a934f05bd181580148d3a2d362 Mon Sep 17 00:00:00 2001 From: Juha Alanen Date: Fri, 7 Feb 2020 12:44:21 +0200 Subject: [build] Enable iOS unit test runner in CI --- circle.yml | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/circle.yml b/circle.yml index cb54ae998a..8417f8e640 100644 --- a/circle.yml +++ b/circle.yml @@ -20,6 +20,7 @@ workflows: - android-render-test-runner - android-unit-test-runner - ios-render-test-runner + - ios-unit-test-runner - baselines: requires: - android-arm64-v8a-release @@ -398,6 +399,74 @@ jobs: fi fi - save + ios-unit-test-runner: + executor: macos-11_0_0 + steps: + - checkout + - prepare + - prepare-macos + - run: + name: Prepare codesign keychain + command: | + cd test/ios + fastlane run create_keychain name:fastlane_keychain password:$FASTLANE_PASSWORD timeout:false unlock:true + fastlane match + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k $FASTLANE_PASSWORD fastlane_keychain + /usr/bin/env xcrun security find-identity -v -p codesigning + - run: + name: Build IOS UnitTestsApp + command: | + cd test/ios + ccache --zero-stats --max-size=2G + cmake ../.. -B Build -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DMBGL_IOS_UNIT_TEST=1 -DCMAKE_OSX_ARCHITECTURES=arm64e + cmake --build Build --config Release + ccache --show-stats + - run: + name: Codesign UnitTestsApp for running on a physical device + command: | + cd test/ios + ./codesigning/generate-entitlements.swift + cd Build + ../codesigning/codesign_all.sh + codesign -dv --verbose=4 Release-iphoneos/UnitTestsApp.app + - run: + name: Login to IOS Google Cloud Platform + command: | + if [[ -n "${GCLOUD_SERVICE_ACCOUNT_JSON_IOS}" ]]; then + echo "${GCLOUD_SERVICE_ACCOUNT_JSON_IOS}" > iosAccount.json + gcloud auth activate-service-account --key-file iosAccount.json --project ios-mapbox-gl-native + rm iosAccount.json + fi + - run: + name: Run UnitTestsApp on Firebase + no_output_timeout: 20m + command: | + if [[ -n "${GCLOUD_SERVICE_ACCOUNT_JSON_IOS}" ]]; then + # arrange files in a way Firebase expects it, and package them in a zip file + cd test/ios/Build + cp ../UnitTestsApp_iphoneos13.2-arm64e-release.xctestrun . + zip testapp.zip -r Release-iphoneos/UnitTestsApp.app --quiet + zip testapp.zip UnitTestsApp_iphoneos13.2-arm64e-release.xctestrun + gcloud firebase test ios models list + gcloud firebase test ios run \ + --test testapp.zip \ + --device model=iphonexs,version=12.0,locale=en,orientation=portrait --xcode-version=11.1 --timeout 20m \ + --verbosity=debug --no-record-video --results-dir ios-unit-test-app-${CIRCLE_BUILD_NUM} + fi + - run: + name: Retrieve Test Result from gcloud + when: always + command: | + if [[ -n "${GCLOUD_SERVICE_ACCOUNT_JSON_IOS}" ]]; then + testResult=$(gsutil ls -d gs://test-lab-hn7kwqcz3108z-hjm4qtbqqkymk/ios-unit-test-app-${CIRCLE_BUILD_NUM}/iphonexs-12.0-en-portrait/TestLogs/) + mkdir -p unit-test-app + gsutil -m cp -r $testResult unit-test-app + cd unit-test-app/TestLogs + xcparse attachments *.xcresult && ls + cd ../.. && mkdir -p /tmp/tests/unit-test + if ls unit-test-app/TestLogs/*.xml 1> /dev/null 2>&1; then cp unit-test-app/TestLogs/*.xml /tmp/tests/unit-test/results.xml; fi + fi + - save android-benchmark-runner: executor: ubuntu-disco steps: -- cgit v1.2.1 From 7a9f8027ac1aa93c5e073d4fe138414059125fa8 Mon Sep 17 00:00:00 2001 From: Juha Alanen Date: Tue, 4 Feb 2020 13:58:19 +0200 Subject: [build] Enable ccache for Xcode iOS builds --- CMakeLists.txt | 20 ++++++++++++++++++++ scripts/ci/ccache-c.in | 9 +++++++++ scripts/ci/ccache-cxx.in | 9 +++++++++ 3 files changed, 38 insertions(+) create mode 100644 scripts/ci/ccache-c.in create mode 100644 scripts/ci/ccache-cxx.in diff --git a/CMakeLists.txt b/CMakeLists.txt index e008db2117..4509f08e73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,26 @@ cmake_minimum_required(VERSION 3.10 FATAL_ERROR) project("Mapbox GL Native" LANGUAGES CXX C) +find_program(CCACHE_PROGRAM ccache) +if(CCACHE_PROGRAM AND CMAKE_SYSTEM_NAME STREQUAL "iOS") + # Set up wrapper scripts + set(C_LAUNCHER "${CCACHE_PROGRAM}") + set(CXX_LAUNCHER "${CCACHE_PROGRAM}") + configure_file(${PROJECT_SOURCE_DIR}/scripts/ci/ccache-c.in ccache-c) + configure_file(${PROJECT_SOURCE_DIR}/scripts/ci/ccache-cxx.in ccache-cxx) + execute_process( + COMMAND + chmod + a+rx + "${CMAKE_BINARY_DIR}/ccache-c" + "${CMAKE_BINARY_DIR}/ccache-cxx" + ) + + # Set Xcode project attributes to route compilation and linking through our scripts + set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/ccache-c") + set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/ccache-cxx") +endif() + set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER Core) diff --git a/scripts/ci/ccache-c.in b/scripts/ci/ccache-c.in new file mode 100644 index 0000000000..f75d456e5d --- /dev/null +++ b/scripts/ci/ccache-c.in @@ -0,0 +1,9 @@ +#!/bin/sh + +# Xcode generator doesn't include the compiler as the +# first argument, Ninja and Makefiles do. Handle both cases. +if [[ "$1" = "${CMAKE_C_COMPILER}" ]] ; then + shift +fi + +exec "${C_LAUNCHER}" "${CMAKE_C_COMPILER}" "$@" diff --git a/scripts/ci/ccache-cxx.in b/scripts/ci/ccache-cxx.in new file mode 100644 index 0000000000..81831ad4dc --- /dev/null +++ b/scripts/ci/ccache-cxx.in @@ -0,0 +1,9 @@ +#!/bin/sh + +# Xcode generator doesn't include the compiler as the +# first argument, Ninja and Makefiles do. Handle both cases. +if [[ "$1" = "${CMAKE_CXX_COMPILER}" ]] ; then + shift +fi + +exec "${CXX_LAUNCHER}" "${CMAKE_CXX_COMPILER}" "$@" -- cgit v1.2.1 From 8f8eb46c7cdf837874efa0a8a0599cf4136e3d34 Mon Sep 17 00:00:00 2001 From: Juha Alanen Date: Wed, 12 Feb 2020 12:45:04 +0200 Subject: [build] Use all available cores for macOS CI builds --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index 8417f8e640..661b64b53d 100644 --- a/circle.yml +++ b/circle.yml @@ -237,7 +237,7 @@ commands: name: Build command: | ccache --zero-stats --max-size=2G - cmake --build build -j $(nproc) << parameters.build_params >> + cmake --build build -j $(nproc 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null) << parameters.build_params >> ccache --show-stats install: steps: -- cgit v1.2.1 From f44cfa2fbc1db9965bc830f5c1e74816869fafa2 Mon Sep 17 00:00:00 2001 From: Juha Alanen Date: Wed, 12 Feb 2020 12:36:17 +0200 Subject: [build] Build iOS release for iPhone instead of simulator --- circle.yml | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/circle.yml b/circle.yml index 661b64b53d..843c56c8be 100644 --- a/circle.yml +++ b/circle.yml @@ -152,7 +152,12 @@ workflows: - macos-xcode11-release config_params: '-G Ninja -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_BUILD_TYPE=Debug' style_tests: true - - ios-xcode11-release + - build-template: + name: ios-xcode11-release + executor_name: macos-11_0_0 + target_is_macos: true + config_params: '-G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=arm64e -DCMAKE_OSX_SYSROOT=iphoneos' + build_params: '--config Release' # # Executors: we currently support two executors, one based on Ubuntu 19.04 aka Disco @@ -312,18 +317,6 @@ commands: gcloud auth activate-service-account --key-file secret.json --project android-gl-native rm secret.json jobs: - ios-xcode11-release: - executor: macos-11_0_0 - steps: - - checkout - - prepare - - prepare-macos - - run: - name: Build - command: | - cmake . -B Build -G Xcode -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_ARCHITECTURES=x86_64 -DCMAKE_OSX_SYSROOT=iphonesimulator - cd Build && xcodebuild -sdk iphonesimulator -project Mapbox\ GL\ Native.xcodeproj -configuration Release - - save ios-render-test-runner: executor: macos-11_0_0 steps: -- cgit v1.2.1 From 6d815401b10aaf7facba5f0676931a9908c1ba5b Mon Sep 17 00:00:00 2001 From: Juha Alanen Date: Thu, 13 Feb 2020 14:12:44 +0200 Subject: [test-runner] Share common code between iOS test runners --- platform/ios/ios.cmake | 82 +++++------- platform/ios/test/common/AppDelegate.h | 7 + platform/ios/test/common/AppDelegate.m | 38 ++++++ platform/ios/test/common/LaunchScreen.storyboard | 27 ++++ platform/ios/test/common/Main.storyboard | 27 ++++ platform/ios/test/common/Tests.m | 37 ++++++ platform/ios/test/common/ViewController.h | 6 + platform/ios/test/common/ViewController.m | 22 ++++ platform/ios/test/common/ios_test_runner.hpp | 14 ++ platform/ios/test/common/main.m | 9 ++ render-test/ios/AppDelegate.h | 7 - render-test/ios/AppDelegate.m | 38 ------ render-test/ios/Gemfile | 3 - render-test/ios/Gemfile.lock | 159 ----------------------- render-test/ios/LaunchScreen.storyboard | 27 ---- render-test/ios/Main.storyboard | 27 ---- render-test/ios/ViewController.h | 6 - render-test/ios/ViewController.m | 22 ---- render-test/ios/ios_test_runner.hpp | 14 -- test/ios/AppDelegate.h | 7 - test/ios/AppDelegate.m | 38 ------ test/ios/Gemfile | 3 - test/ios/LaunchScreen.storyboard | 27 ---- test/ios/Main.storyboard | 27 ---- test/ios/ViewController.h | 6 - test/ios/ViewController.m | 22 ---- test/ios/iosTestRunner.mm | 2 +- test/ios/ios_test_runner.cpp | 2 +- test/ios/ios_test_runner.hpp | 14 -- test/ios/main.m | 9 -- test/ios/tests/Tests.m | 37 ------ 31 files changed, 222 insertions(+), 544 deletions(-) create mode 100644 platform/ios/test/common/AppDelegate.h create mode 100644 platform/ios/test/common/AppDelegate.m create mode 100644 platform/ios/test/common/LaunchScreen.storyboard create mode 100644 platform/ios/test/common/Main.storyboard create mode 100644 platform/ios/test/common/Tests.m create mode 100644 platform/ios/test/common/ViewController.h create mode 100644 platform/ios/test/common/ViewController.m create mode 100644 platform/ios/test/common/ios_test_runner.hpp create mode 100644 platform/ios/test/common/main.m delete mode 100644 render-test/ios/AppDelegate.h delete mode 100644 render-test/ios/AppDelegate.m delete mode 100644 render-test/ios/Gemfile delete mode 100644 render-test/ios/Gemfile.lock delete mode 100644 render-test/ios/LaunchScreen.storyboard delete mode 100644 render-test/ios/Main.storyboard delete mode 100644 render-test/ios/ViewController.h delete mode 100644 render-test/ios/ViewController.m delete mode 100644 render-test/ios/ios_test_runner.hpp delete mode 100644 test/ios/AppDelegate.h delete mode 100644 test/ios/AppDelegate.m delete mode 100644 test/ios/Gemfile delete mode 100644 test/ios/LaunchScreen.storyboard delete mode 100644 test/ios/Main.storyboard delete mode 100644 test/ios/ViewController.h delete mode 100644 test/ios/ViewController.m delete mode 100644 test/ios/ios_test_runner.hpp delete mode 100644 test/ios/main.m delete mode 100644 test/ios/tests/Tests.m diff --git a/platform/ios/ios.cmake b/platform/ios/ios.cmake index 85b22afcc0..16d0ed41c2 100644 --- a/platform/ios/ios.cmake +++ b/platform/ios/ios.cmake @@ -94,30 +94,26 @@ target_link_libraries( ) if(MBGL_IOS_RENDER_TEST) - set(CMAKE_OSX_ARCHITECTURES "armv7;i386;x86_64;arm64") - include(${PROJECT_SOURCE_DIR}/vendor/zip-archive.cmake) initialize_ios_target(mbgl-vendor-zip-archive) set(PREPARE_CMD "${PROJECT_SOURCE_DIR}/render-test/ios/setup_test_data.sh") - message("COMMAND: ${PREPARE_CMD}") execute_process(COMMAND ${PREPARE_CMD} RESULT_VARIABLE CMD_ERROR WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) - message(STATUS "CMD_ERROR:" ${CMD_ERROR}) - set(RESOURCES ${PROJECT_SOURCE_DIR}/render-test/ios/Main.storyboard ${PROJECT_SOURCE_DIR}/render-test/ios/LaunchScreen.storyboard - ${PROJECT_SOURCE_DIR}/test-data) + set(RESOURCES ${PROJECT_SOURCE_DIR}/platform/ios/test/common/Main.storyboard + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/LaunchScreen.storyboard ${PROJECT_SOURCE_DIR}/test-data) add_executable( RenderTestApp - ${PROJECT_SOURCE_DIR}/render-test/ios/ios_test_runner.hpp + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/ios_test_runner.hpp + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/AppDelegate.h + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/AppDelegate.m + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/ViewController.h + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/ViewController.m + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/main.m ${PROJECT_SOURCE_DIR}/render-test/ios/ios_test_runner.cpp - ${PROJECT_SOURCE_DIR}/render-test/ios/AppDelegate.h - ${PROJECT_SOURCE_DIR}/render-test/ios/AppDelegate.m - ${PROJECT_SOURCE_DIR}/render-test/ios/ViewController.h - ${PROJECT_SOURCE_DIR}/render-test/ios/ViewController.m ${PROJECT_SOURCE_DIR}/render-test/ios/iosTestRunner.h ${PROJECT_SOURCE_DIR}/render-test/ios/iosTestRunner.mm - ${PROJECT_SOURCE_DIR}/render-test/ios/main.m ${RESOURCES} ) initialize_ios_target(RenderTestApp) @@ -147,6 +143,7 @@ if(MBGL_IOS_RENDER_TEST) ${PROJECT_SOURCE_DIR}/platform/darwin/include ${PROJECT_SOURCE_DIR}/platform/darwin/include/mbgl/interface/ ${PROJECT_SOURCE_DIR}/platform/default/include + ${PROJECT_SOURCE_DIR}/platform/ios/test/common ${PROJECT_SOURCE_DIR}/src ) @@ -168,19 +165,13 @@ if(MBGL_IOS_RENDER_TEST) mbgl-vendor-zip-archive ) + set_target_properties(RenderTestApp PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "") + set_target_properties(RenderTestApp PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") + find_package(XCTest REQUIRED) xctest_add_bundle(RenderTestAppTests RenderTestApp ${PROJECT_SOURCE_DIR}/render-test/ios/tests/Tests.m) - set_target_properties( - RenderTestAppTests - PROPERTIES - XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET - "${IOS_DEPLOYMENT_TARGET}" - XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH - $<$:YES> - ) - target_include_directories( RenderTestAppTests PUBLIC ${PROJECT_SOURCE_DIR}/render-test/ios @@ -188,7 +179,11 @@ if(MBGL_IOS_RENDER_TEST) xctest_add_test(XCTest.RenderTestApp RenderTestAppTests) + set_target_properties(RenderTestAppTests PROPERTIES XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${IOS_DEPLOYMENT_TARGET}") + set_target_properties(RenderTestAppTests PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH $<$:YES>) set_target_properties(RenderTestAppTests PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/render-test/ios/tests/Info.plist) + set_target_properties(RenderTestAppTests PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "") + set_target_properties(RenderTestAppTests PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") endif() if(MBGL_IOS_UNIT_TEST) @@ -199,24 +194,20 @@ if(MBGL_IOS_UNIT_TEST) ${CMAKE_CURRENT_BINARY_DIR}/test-data/mapbox-gl-js/src/style-spec/reference ) - set( - RESOURCES - ${PROJECT_SOURCE_DIR}/test/ios/Main.storyboard - ${PROJECT_SOURCE_DIR}/test/ios/LaunchScreen.storyboard - ${CMAKE_CURRENT_BINARY_DIR}/test-data - ) + set(RESOURCES ${PROJECT_SOURCE_DIR}/platform/ios/test/common/Main.storyboard + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/LaunchScreen.storyboard ${CMAKE_CURRENT_BINARY_DIR}/test-data) add_executable( UnitTestsApp - ${PROJECT_SOURCE_DIR}/test/ios/ios_test_runner.hpp + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/ios_test_runner.hpp + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/AppDelegate.h + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/AppDelegate.m + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/ViewController.h + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/ViewController.m + ${PROJECT_SOURCE_DIR}/platform/ios/test/common/main.m ${PROJECT_SOURCE_DIR}/test/ios/ios_test_runner.cpp - ${PROJECT_SOURCE_DIR}/test/ios/AppDelegate.h - ${PROJECT_SOURCE_DIR}/test/ios/AppDelegate.m - ${PROJECT_SOURCE_DIR}/test/ios/ViewController.h - ${PROJECT_SOURCE_DIR}/test/ios/ViewController.m ${PROJECT_SOURCE_DIR}/test/ios/iosTestRunner.h ${PROJECT_SOURCE_DIR}/test/ios/iosTestRunner.mm - ${PROJECT_SOURCE_DIR}/test/ios/main.m ${RESOURCES} ) initialize_ios_target(UnitTestsApp) @@ -236,12 +227,11 @@ if(MBGL_IOS_UNIT_TEST) target_include_directories( UnitTestsApp - PUBLIC {MBGL_ROOT}/test/include ${PROJECT_SOURCE_DIR}/include - ) - - target_include_directories( - UnitTestsApp - PUBLIC ${PROJECT_SOURCE_DIR}/test/ios + PUBLIC + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/platform/ios/test/common + ${PROJECT_SOURCE_DIR}/test/include + ${PROJECT_SOURCE_DIR}/test/ios ) target_link_libraries( @@ -263,16 +253,7 @@ if(MBGL_IOS_UNIT_TEST) find_package(XCTest REQUIRED) - xctest_add_bundle(UnitTestsAppTests UnitTestsApp ${PROJECT_SOURCE_DIR}/test/ios/tests/Tests.m) - - set_target_properties( - UnitTestsAppTests - PROPERTIES - XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET - "${IOS_DEPLOYMENT_TARGET}" - XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH - $<$:YES> - ) + xctest_add_bundle(UnitTestsAppTests UnitTestsApp ${PROJECT_SOURCE_DIR}/platform/ios/test/common/Tests.m) target_include_directories( UnitTestsAppTests @@ -281,8 +262,11 @@ if(MBGL_IOS_UNIT_TEST) xctest_add_test(XCTest.UnitTestsApp UnitTestsAppTests) + set_target_properties(UnitTestsAppTests PROPERTIES XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${IOS_DEPLOYMENT_TARGET}") + set_target_properties(UnitTestsAppTests PROPERTIES XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH $<$:YES>) set_target_properties(UnitTestsAppTests PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${PROJECT_SOURCE_DIR}/test/ios/tests/Info.plist) set_target_properties(UnitTestsAppTests PROPERTIES XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "") set_target_properties(UnitTestsAppTests PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO") endif() + unset(IOS_DEPLOYMENT_TARGET CACHE) diff --git a/platform/ios/test/common/AppDelegate.h b/platform/ios/test/common/AppDelegate.h new file mode 100644 index 0000000000..134c8063dc --- /dev/null +++ b/platform/ios/test/common/AppDelegate.h @@ -0,0 +1,7 @@ +#import // UIApplicationDelegate + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + +@end \ No newline at end of file diff --git a/platform/ios/test/common/AppDelegate.m b/platform/ios/test/common/AppDelegate.m new file mode 100644 index 0000000000..874d18de2a --- /dev/null +++ b/platform/ios/test/common/AppDelegate.m @@ -0,0 +1,38 @@ +#import "AppDelegate.h" + +@interface AppDelegate() + +@end + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + // Insert code here to initialize your application + NSLog(@"didFinishLaunchingWithOptions"); + return YES; +} + +- (void)applicationWillResignActive:(UIApplication *)application { + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. +} + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. +} + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + + +@end diff --git a/platform/ios/test/common/LaunchScreen.storyboard b/platform/ios/test/common/LaunchScreen.storyboard new file mode 100644 index 0000000000..c9b7564332 --- /dev/null +++ b/platform/ios/test/common/LaunchScreen.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/ios/test/common/Main.storyboard b/platform/ios/test/common/Main.storyboard new file mode 100644 index 0000000000..34d4c7e2ec --- /dev/null +++ b/platform/ios/test/common/Main.storyboard @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/platform/ios/test/common/Tests.m b/platform/ios/test/common/Tests.m new file mode 100644 index 0000000000..8d0719705a --- /dev/null +++ b/platform/ios/test/common/Tests.m @@ -0,0 +1,37 @@ +#import +#import "iosTestRunner.h" +@interface Tests : XCTestCase + +@end + +@implementation Tests + +- (void)setUp { + [super setUp]; +} + +- (void)tearDown { + [super tearDown]; +} + +- (void)testStartTestRunner { + IosTestRunner* runner = [[IosTestRunner alloc] init]; + XCTAssert(runner, @"IOSTestRunner is not initialized correctly"); + + NSString* testResult = [runner getResultPath]; + XCTAssert(testResult, @"IOSTestRunner did not produce a test result file"); + + NSFileManager *fileManager = [NSFileManager defaultManager]; + BOOL fileFound = [fileManager fileExistsAtPath: testResult]; + XCTAssert(fileFound, @"Test result file '%@' does not exit", testResult); + NSURL *resultURL = [NSURL fileURLWithPath:testResult]; + XCTAttachment *attachment1URL = [XCTAttachment attachmentWithContentsOfFileAtURL: resultURL]; + XCTAssert(attachment1URL, @"Failed to attach test result '%@'", testResult); + attachment1URL.lifetime = XCTAttachmentLifetimeKeepAlways; + [self addAttachment:attachment1URL]; + + BOOL success = [runner getTestStatus]; + XCTAssert(success, @"IOSTestRunner reports error because some of the tests are not passed, please check the test report"); +} + +@end diff --git a/platform/ios/test/common/ViewController.h b/platform/ios/test/common/ViewController.h new file mode 100644 index 0000000000..9c7dfc57ec --- /dev/null +++ b/platform/ios/test/common/ViewController.h @@ -0,0 +1,6 @@ +#import + +@interface ViewController : UIViewController + +@end + diff --git a/platform/ios/test/common/ViewController.m b/platform/ios/test/common/ViewController.m new file mode 100644 index 0000000000..e9c526122a --- /dev/null +++ b/platform/ios/test/common/ViewController.m @@ -0,0 +1,22 @@ +#import "ViewController.h" +#import "iosTestRunner.h" + +@interface ViewController () +{ + IosTestRunner* i; +} +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; +// In order to run test runner with app itself instead of with unit test, comment out the following line. +// i = [[IosTestRunner alloc]init]; +} + +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; +} + +@end diff --git a/platform/ios/test/common/ios_test_runner.hpp b/platform/ios/test/common/ios_test_runner.hpp new file mode 100644 index 0000000000..db263dc73c --- /dev/null +++ b/platform/ios/test/common/ios_test_runner.hpp @@ -0,0 +1,14 @@ +#ifndef ios_test_runner_hpp +#define ios_test_runner_hpp + +#include + +class TestRunner { +public: + TestRunner() = default; + ~TestRunner() = default; + + bool startTest(const std::string& path); +}; + +#endif /* ios_test_runner_hpp */ diff --git a/platform/ios/test/common/main.m b/platform/ios/test/common/main.m new file mode 100644 index 0000000000..f813c8fea9 --- /dev/null +++ b/platform/ios/test/common/main.m @@ -0,0 +1,9 @@ +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) +{ + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/render-test/ios/AppDelegate.h b/render-test/ios/AppDelegate.h deleted file mode 100644 index 134c8063dc..0000000000 --- a/render-test/ios/AppDelegate.h +++ /dev/null @@ -1,7 +0,0 @@ -#import // UIApplicationDelegate - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - -@end \ No newline at end of file diff --git a/render-test/ios/AppDelegate.m b/render-test/ios/AppDelegate.m deleted file mode 100644 index 874d18de2a..0000000000 --- a/render-test/ios/AppDelegate.m +++ /dev/null @@ -1,38 +0,0 @@ -#import "AppDelegate.h" - -@interface AppDelegate() - -@end - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Insert code here to initialize your application - NSLog(@"didFinishLaunchingWithOptions"); - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - - -@end diff --git a/render-test/ios/Gemfile b/render-test/ios/Gemfile deleted file mode 100644 index adc90d98cf..0000000000 --- a/render-test/ios/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source "https://rubygems.org" - -gem "fastlane" \ No newline at end of file diff --git a/render-test/ios/Gemfile.lock b/render-test/ios/Gemfile.lock deleted file mode 100644 index 23018150b9..0000000000 --- a/render-test/ios/Gemfile.lock +++ /dev/null @@ -1,159 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - CFPropertyList (3.0.2) - addressable (2.7.0) - public_suffix (>= 2.0.2, < 5.0) - atomos (0.1.3) - babosa (1.0.3) - claide (1.0.3) - colored (1.2) - colored2 (3.1.2) - commander-fastlane (4.4.6) - highline (~> 1.7.2) - declarative (0.0.10) - declarative-option (0.1.0) - digest-crc (0.4.1) - domain_name (0.5.20190701) - unf (>= 0.0.5, < 1.0.0) - dotenv (2.7.5) - emoji_regex (1.0.1) - excon (0.71.1) - faraday (0.17.3) - multipart-post (>= 1.2, < 3) - faraday-cookie_jar (0.0.6) - faraday (>= 0.7.4) - http-cookie (~> 1.0.0) - faraday_middleware (0.13.1) - faraday (>= 0.7.4, < 1.0) - fastimage (2.1.7) - fastlane (2.139.0) - CFPropertyList (>= 2.3, < 4.0.0) - addressable (>= 2.3, < 3.0.0) - babosa (>= 1.0.2, < 2.0.0) - bundler (>= 1.12.0, < 3.0.0) - colored - commander-fastlane (>= 4.4.6, < 5.0.0) - dotenv (>= 2.1.1, < 3.0.0) - emoji_regex (>= 0.1, < 2.0) - excon (>= 0.71.0, < 1.0.0) - faraday (~> 0.17) - faraday-cookie_jar (~> 0.0.6) - faraday_middleware (~> 0.13.1) - fastimage (>= 2.1.0, < 3.0.0) - gh_inspector (>= 1.1.2, < 2.0.0) - google-api-client (>= 0.29.2, < 0.37.0) - google-cloud-storage (>= 1.15.0, < 2.0.0) - highline (>= 1.7.2, < 2.0.0) - json (< 3.0.0) - jwt (~> 2.1.0) - mini_magick (>= 4.9.4, < 5.0.0) - multi_xml (~> 0.5) - multipart-post (~> 2.0.0) - plist (>= 3.1.0, < 4.0.0) - public_suffix (~> 2.0.0) - rubyzip (>= 1.3.0, < 2.0.0) - security (= 0.1.3) - simctl (~> 1.6.3) - slack-notifier (>= 2.0.0, < 3.0.0) - terminal-notifier (>= 2.0.0, < 3.0.0) - terminal-table (>= 1.4.5, < 2.0.0) - tty-screen (>= 0.6.3, < 1.0.0) - tty-spinner (>= 0.8.0, < 1.0.0) - word_wrap (~> 1.0.0) - xcodeproj (>= 1.13.0, < 2.0.0) - xcpretty (~> 0.3.0) - xcpretty-travis-formatter (>= 0.0.3) - gh_inspector (1.1.3) - google-api-client (0.36.4) - addressable (~> 2.5, >= 2.5.1) - googleauth (~> 0.9) - httpclient (>= 2.8.1, < 3.0) - mini_mime (~> 1.0) - representable (~> 3.0) - retriable (>= 2.0, < 4.0) - signet (~> 0.12) - google-cloud-core (1.4.1) - google-cloud-env (~> 1.0) - google-cloud-env (1.3.0) - faraday (~> 0.11) - google-cloud-storage (1.25.0) - addressable (~> 2.5) - digest-crc (~> 0.4) - google-api-client (~> 0.33) - google-cloud-core (~> 1.2) - googleauth (~> 0.9) - mini_mime (~> 1.0) - googleauth (0.10.0) - faraday (~> 0.12) - jwt (>= 1.4, < 3.0) - memoist (~> 0.16) - multi_json (~> 1.11) - os (>= 0.9, < 2.0) - signet (~> 0.12) - highline (1.7.10) - http-cookie (1.0.3) - domain_name (~> 0.5) - httpclient (2.8.3) - json (2.3.0) - jwt (2.1.0) - memoist (0.16.2) - mini_magick (4.10.1) - mini_mime (1.0.2) - multi_json (1.14.1) - multi_xml (0.6.0) - multipart-post (2.0.0) - nanaimo (0.2.6) - naturally (2.2.0) - os (1.0.1) - plist (3.5.0) - public_suffix (2.0.5) - representable (3.0.4) - declarative (< 0.1.0) - declarative-option (< 0.2.0) - uber (< 0.2.0) - retriable (3.1.2) - rouge (2.0.7) - rubyzip (1.3.0) - security (0.1.3) - signet (0.12.0) - addressable (~> 2.3) - faraday (~> 0.9) - jwt (>= 1.5, < 3.0) - multi_json (~> 1.10) - simctl (1.6.7) - CFPropertyList - naturally - slack-notifier (2.3.2) - terminal-notifier (2.0.0) - terminal-table (1.8.0) - unicode-display_width (~> 1.1, >= 1.1.1) - tty-cursor (0.7.0) - tty-screen (0.7.0) - tty-spinner (0.9.2) - tty-cursor (~> 0.7) - uber (0.1.0) - unf (0.1.4) - unf_ext - unf_ext (0.0.7.6) - unicode-display_width (1.6.0) - word_wrap (1.0.0) - xcodeproj (1.14.0) - CFPropertyList (>= 2.3.3, < 4.0) - atomos (~> 0.1.3) - claide (>= 1.0.2, < 2.0) - colored2 (~> 3.1) - nanaimo (~> 0.2.6) - xcpretty (0.3.0) - rouge (~> 2.0.7) - xcpretty-travis-formatter (1.0.0) - xcpretty (~> 0.2, >= 0.0.7) - -PLATFORMS - ruby - -DEPENDENCIES - fastlane - -BUNDLED WITH - 2.1.4 diff --git a/render-test/ios/LaunchScreen.storyboard b/render-test/ios/LaunchScreen.storyboard deleted file mode 100644 index c9b7564332..0000000000 --- a/render-test/ios/LaunchScreen.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/render-test/ios/Main.storyboard b/render-test/ios/Main.storyboard deleted file mode 100644 index 34d4c7e2ec..0000000000 --- a/render-test/ios/Main.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/render-test/ios/ViewController.h b/render-test/ios/ViewController.h deleted file mode 100644 index 9c7dfc57ec..0000000000 --- a/render-test/ios/ViewController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface ViewController : UIViewController - -@end - diff --git a/render-test/ios/ViewController.m b/render-test/ios/ViewController.m deleted file mode 100644 index e9c526122a..0000000000 --- a/render-test/ios/ViewController.m +++ /dev/null @@ -1,22 +0,0 @@ -#import "ViewController.h" -#import "iosTestRunner.h" - -@interface ViewController () -{ - IosTestRunner* i; -} -@end - -@implementation ViewController - -- (void)viewDidLoad { - [super viewDidLoad]; -// In order to run test runner with app itself instead of with unit test, comment out the following line. -// i = [[IosTestRunner alloc]init]; -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -@end diff --git a/render-test/ios/ios_test_runner.hpp b/render-test/ios/ios_test_runner.hpp deleted file mode 100644 index 4ec1da93b0..0000000000 --- a/render-test/ios/ios_test_runner.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef ios_test_runner_hpp -#define ios_test_runner_hpp - -#include - -class TestRunner { -public: - TestRunner() = default; - ~TestRunner() = default; - - bool startTest(const std::string& manifest); -}; - -#endif /* ios_test_runner_hpp */ diff --git a/test/ios/AppDelegate.h b/test/ios/AppDelegate.h deleted file mode 100644 index 134c8063dc..0000000000 --- a/test/ios/AppDelegate.h +++ /dev/null @@ -1,7 +0,0 @@ -#import // UIApplicationDelegate - -@interface AppDelegate : UIResponder - -@property (strong, nonatomic) UIWindow *window; - -@end \ No newline at end of file diff --git a/test/ios/AppDelegate.m b/test/ios/AppDelegate.m deleted file mode 100644 index 874d18de2a..0000000000 --- a/test/ios/AppDelegate.m +++ /dev/null @@ -1,38 +0,0 @@ -#import "AppDelegate.h" - -@interface AppDelegate() - -@end - -@implementation AppDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Insert code here to initialize your application - NSLog(@"didFinishLaunchingWithOptions"); - return YES; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. - // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. -} - -- (void)applicationWillTerminate:(UIApplication *)application { - // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. -} - - -@end diff --git a/test/ios/Gemfile b/test/ios/Gemfile deleted file mode 100644 index adc90d98cf..0000000000 --- a/test/ios/Gemfile +++ /dev/null @@ -1,3 +0,0 @@ -source "https://rubygems.org" - -gem "fastlane" \ No newline at end of file diff --git a/test/ios/LaunchScreen.storyboard b/test/ios/LaunchScreen.storyboard deleted file mode 100644 index c9b7564332..0000000000 --- a/test/ios/LaunchScreen.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/ios/Main.storyboard b/test/ios/Main.storyboard deleted file mode 100644 index 34d4c7e2ec..0000000000 --- a/test/ios/Main.storyboard +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/ios/ViewController.h b/test/ios/ViewController.h deleted file mode 100644 index 9c7dfc57ec..0000000000 --- a/test/ios/ViewController.h +++ /dev/null @@ -1,6 +0,0 @@ -#import - -@interface ViewController : UIViewController - -@end - diff --git a/test/ios/ViewController.m b/test/ios/ViewController.m deleted file mode 100644 index e9c526122a..0000000000 --- a/test/ios/ViewController.m +++ /dev/null @@ -1,22 +0,0 @@ -#import "ViewController.h" -#import "iosTestRunner.h" - -@interface ViewController () -{ - IosTestRunner* i; -} -@end - -@implementation ViewController - -- (void)viewDidLoad { - [super viewDidLoad]; -// In order to run test runner with app itself instead of with unit test, comment out the following line. -// i = [[IosTestRunner alloc]init]; -} - -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; -} - -@end diff --git a/test/ios/iosTestRunner.mm b/test/ios/iosTestRunner.mm index 383b9036ec..d3f6113a05 100644 --- a/test/ios/iosTestRunner.mm +++ b/test/ios/iosTestRunner.mm @@ -1,6 +1,6 @@ #import "iosTestRunner.h" -#include "ios_test_runner.hpp" +#include #include diff --git a/test/ios/ios_test_runner.cpp b/test/ios/ios_test_runner.cpp index 293a2955b5..c99d8c3f30 100644 --- a/test/ios/ios_test_runner.cpp +++ b/test/ios/ios_test_runner.cpp @@ -1,4 +1,4 @@ -#include "ios_test_runner.hpp" +#include #include diff --git a/test/ios/ios_test_runner.hpp b/test/ios/ios_test_runner.hpp deleted file mode 100644 index 3edae22828..0000000000 --- a/test/ios/ios_test_runner.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef ios_test_runner_hpp -#define ios_test_runner_hpp - -#include - -class TestRunner { -public: - TestRunner() = default; - ~TestRunner() = default; - - bool startTest(const std::string& basePath); -}; - -#endif /* ios_test_runner_hpp */ diff --git a/test/ios/main.m b/test/ios/main.m deleted file mode 100644 index f813c8fea9..0000000000 --- a/test/ios/main.m +++ /dev/null @@ -1,9 +0,0 @@ -#import -#import "AppDelegate.h" - -int main(int argc, char * argv[]) -{ - @autoreleasepool { - return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); - } -} diff --git a/test/ios/tests/Tests.m b/test/ios/tests/Tests.m deleted file mode 100644 index 4c2131d61c..0000000000 --- a/test/ios/tests/Tests.m +++ /dev/null @@ -1,37 +0,0 @@ -#import -#import "iosTestRunner.h" -@interface Tests : XCTestCase - -@end - -@implementation Tests - -- (void)setUp { - [super setUp]; -} - -- (void)tearDown { - [super tearDown]; -} - -- (void)testStartUnitTestRunner { - IosTestRunner* runner = [[IosTestRunner alloc] init]; - XCTAssert(runner, @"IOSTestRunner is not initialized correctly"); - - NSString* testResult = [runner getResultPath]; - XCTAssert(testResult, @"IOSTestRunner did not produce a test result file"); - - NSFileManager *fileManager = [NSFileManager defaultManager]; - BOOL fileFound = [fileManager fileExistsAtPath: testResult]; - XCTAssert(fileFound, @"Test result file '%@' does not exit", testResult); - NSURL *resultURL = [NSURL fileURLWithPath:testResult]; - XCTAttachment *attachment1URL = [XCTAttachment attachmentWithContentsOfFileAtURL: resultURL]; - XCTAssert(attachment1URL, @"Failed to attach test result '%@'", testResult); - attachment1URL.lifetime = XCTAttachmentLifetimeKeepAlways; - [self addAttachment:attachment1URL]; - - BOOL success = [runner getTestStatus]; - XCTAssert(success, @"IOSTestRunner reports error because some of the tests are not passed, please check the test report"); -} - -@end -- cgit v1.2.1 From 112fa0dccf1c3bc71581b184a81470a19cdbcf99 Mon Sep 17 00:00:00 2001 From: Juha Alanen Date: Wed, 12 Feb 2020 12:55:27 +0200 Subject: [build] Cleanup CircleCI configuration The parameters were moved to iOS cmake file, so now the RenderTestApp can be built with cmake. --- circle.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/circle.yml b/circle.yml index 843c56c8be..a9c10b6395 100644 --- a/circle.yml +++ b/circle.yml @@ -335,16 +335,15 @@ jobs: name: Build IOS RenderTestApp command: | cd render-test/ios - cmake ../.. -B Build -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DMBGL_IOS_RENDER_TEST=ON - cd Build - xcodebuild -sdk iphoneos -project Mapbox\ GL\ Native.xcodeproj -scheme RenderTestApp build-for-testing -arch arm64 CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -configuration Release - xcodebuild -sdk iphoneos -project Mapbox\ GL\ Native.xcodeproj build -target RenderTestAppTests -arch arm64 CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO -configuration Release + ccache --zero-stats --max-size=2G + cmake ../.. -B Build -G Xcode -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DMBGL_IOS_RENDER_TEST=ON -DCMAKE_OSX_ARCHITECTURES=arm64e + cmake --build Build --config Release + ccache --show-stats - run: name: Codesign RenderTestApp for running on a physical device command: | cd render-test/ios ./codesigning/generate-entitlements.swift - ls codesigning cd Build ../codesigning/codesign_all.sh codesign -dv --verbose=4 Release-iphoneos/RenderTestApp.app # for debugging that app is signed or not -- cgit v1.2.1 From bf8bde5029bf2cd54a85af5315ad26636109b9a1 Mon Sep 17 00:00:00 2001 From: Juha Alanen Date: Wed, 12 Feb 2020 12:07:30 +0200 Subject: [build] Bump minimum iOS version to 12.0 --- platform/ios/ios.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/ios/ios.cmake b/platform/ios/ios.cmake index 16d0ed41c2..18b2b2aad0 100644 --- a/platform/ios/ios.cmake +++ b/platform/ios/ios.cmake @@ -4,7 +4,7 @@ target_compile_definitions( ) if(NOT DEFINED IOS_DEPLOYMENT_TARGET) - set(IOS_DEPLOYMENT_TARGET "9.0") + set(IOS_DEPLOYMENT_TARGET "12.0") endif() macro(initialize_ios_target target) -- cgit v1.2.1 From 21107e0c1add92fea4ba614dfed968c1c42f41c0 Mon Sep 17 00:00:00 2001 From: Karim Naaji Date: Tue, 11 Feb 2020 17:04:02 -0500 Subject: Port line-dasharray fix from gl-js * Fix artifact for zero-lenghted dash array Fixes issue https://github.com/mapbox/mapbox-gl-js/issues/9213 and add render test for coverage around 0-length dash arrays Update distance field generation for regular dashes as follows: 1. Compute the dash array ranges and stretch location along the distance field 2. Collapse any 0-length distance field range 3. Collapse neighbouring same-type parts into single part * combine consecutive dashes and parts https://github.com/mapbox/mapbox-gl-js/pull/9246 https://github.com/mapbox/mapbox-gl-native/issues/16181 --- src/mbgl/geometry/line_atlas.cpp | 178 ++++++++++++++++++++++++++------------- src/mbgl/geometry/line_atlas.hpp | 7 ++ 2 files changed, 126 insertions(+), 59 deletions(-) diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp index f272101a5b..3b6d82c46c 100644 --- a/src/mbgl/geometry/line_atlas.cpp +++ b/src/mbgl/geometry/line_atlas.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -6,8 +7,6 @@ #include #include -#include - namespace mbgl { namespace { @@ -20,82 +19,143 @@ size_t getDashPatternHash(const std::vector& dasharray, const LinePattern return key; } -LinePatternPos addDashPattern(AlphaImage& image, - const int32_t yOffset, - const std::vector& dasharray, - const LinePatternCap patternCap) { - const uint8_t n = patternCap == LinePatternCap::Round ? 7 : 0; - constexpr const uint8_t offset = 128; +std::vector getDashRanges(const std::vector& dasharray, float stretch) { + // If dasharray has an odd length, both the first and last parts + // are dashes and should be joined seamlessly. + const bool oddDashArray = dasharray.size() % 2 == 1; - if (dasharray.size() < 2) { - Log::Warning(Event::ParseStyle, "line dasharray requires at least two elements"); - return LinePatternPos(); - } + float left = oddDashArray ? -dasharray.back() * stretch : 0.0f; + float right = dasharray.front() * stretch; + bool isDash = true; - float length = 0; - for (const float part : dasharray) { - length += part; + std::vector ranges; + ranges.reserve(dasharray.size()); + ranges.push_back({left, right, isDash, dasharray.front() == 0.0f}); + + float currentDashLength = dasharray.front(); + for (size_t i = 1; i < dasharray.size(); ++i) { + isDash = !isDash; + + const float dashLength = dasharray[i]; + left = currentDashLength * stretch; + currentDashLength += dashLength; + right = currentDashLength * stretch; + + ranges.push_back({left, right, isDash, dashLength == 0.0f}); } - float stretch = image.size.width / length; - float halfWidth = stretch * 0.5; - // If dasharray has an odd length, both the first and last parts - // are dashes and should be joined seamlessly. - bool oddLength = dasharray.size() % 2 == 1; + return ranges; +} + +void addRoundDash( + const std::vector& ranges, uint32_t yOffset, float stretch, const int n, AlphaImage& image) { + const float halfStretch = stretch * 0.5f; for (int y = -n; y <= n; y++) { int row = yOffset + n + y; - int index = image.size.width * row; + const uint32_t index = image.size.width * row; + uint32_t currIndex = 0; + DashRange range = ranges[currIndex]; - float left = 0; - float right = dasharray[0]; - unsigned int partIndex = 1; + for (uint32_t x = 0; x < image.size.width; x++) { + if (x / range.right > 1.0f) { + range = ranges[++currIndex]; + } - if (oddLength) { - left -= dasharray.back(); - } + float distLeft = fabsf(x - range.left); + float distRight = fabsf(x - range.right); + float minDist = fminf(distLeft, distRight); + float signedDistance; - for (uint32_t x = 0; x < image.size.width; x++) { - while (right < x / stretch) { - left = right; - if (partIndex >= dasharray.size()) { - return LinePatternPos(); - } - right = right + dasharray[partIndex]; - - if (oddLength && partIndex == dasharray.size() - 1) { - right += dasharray.front(); - } - - partIndex++; + float distMiddle = static_cast(y) / n * (halfStretch + 1.0f); + if (range.isDash) { + float distEdge = halfStretch - fabsf(distMiddle); + signedDistance = sqrtf(minDist * minDist + distEdge * distEdge); + } else { + signedDistance = halfStretch - sqrtf(minDist * minDist + distMiddle * distMiddle); } - float distLeft = fabs(x - left * stretch); - float distRight = fabs(x - right * stretch); - float dist = fmin(distLeft, distRight); - bool inside = (partIndex % 2) == 1; - int signedDistance; - - if (patternCap == LinePatternCap::Round) { - float distMiddle = n ? (float)y / n * (halfWidth + 1) : 0; - if (inside) { - float distEdge = halfWidth - fabs(distMiddle); - signedDistance = sqrt(dist * dist + distEdge * distEdge); - } else { - signedDistance = halfWidth - sqrt(dist * dist + distMiddle * distMiddle); - } + image.data[index + x] = static_cast(fmaxf(0.0f, fminf(255.0f, signedDistance + 128.0f))); + } + } +} +void addRegularDash(std::vector& ranges, uint32_t yOffset, AlphaImage& image) { + // Collapse any zero-length range + for (auto it = ranges.begin(); it != ranges.end();) { + if (it->isZeroLength) { + ranges.erase(it); + } else { + ++it; + } + } + + if (ranges.size() >= 2) { + // Collapse neighbouring same-type parts into a single part + for (auto curr = ranges.begin(), next = ranges.begin() + 1; curr != ranges.end() && next != ranges.end();) { + if (next->isDash == curr->isDash) { + next->left = curr->left; + ranges.erase(curr); } else { - signedDistance = int((inside ? 1 : -1) * dist); + ++curr; + ++next; } + } + } + + DashRange& first = ranges.front(); + DashRange& last = ranges.back(); + if (first.isDash == last.isDash) { + first.left = last.left - image.size.width; + last.right = first.right + image.size.width; + } + + const uint32_t index = image.size.width * yOffset; + uint32_t currIndex = 0; + DashRange range = ranges[currIndex]; - image.data[index + x] = fmax(0, fmin(255, signedDistance + offset)); + for (uint32_t x = 0; x < image.size.width; ++x) { + if (x / range.right > 1.0f) { + range = ranges[++currIndex]; } + + float distLeft = fabsf(x - range.left); + float distRight = fabsf(x - range.right); + float minDist = fminf(distLeft, distRight); + float signedDistance = range.isDash ? minDist : -minDist; + + image.data[index + x] = static_cast(fmaxf(0.0f, fminf(255.0f, signedDistance + 128.0f))); + } +} + +LinePatternPos addDashPattern(AlphaImage& image, + uint32_t yOffset, + const std::vector& dasharray, + const LinePatternCap patternCap) { + const uint8_t n = patternCap == LinePatternCap::Round ? 7 : 0; + + if (dasharray.size() < 2) { + Log::Warning(Event::ParseStyle, "line dasharray requires at least two elements"); + return LinePatternPos(); + } + + float length = 0; + for (const float part : dasharray) { + length += part; + } + + float stretch = image.size.width / length; + std::vector ranges = getDashRanges(dasharray, stretch); + + if (patternCap == LinePatternCap::Round) { + addRoundDash(ranges, yOffset, stretch, n, image); + } else { + addRegularDash(ranges, yOffset, image); } LinePatternPos position; - position.y = (0.5 + yOffset + n) / image.size.height; - position.height = (2.0 * n + 1) / image.size.height; + position.y = (0.5f + yOffset + n) / image.size.height; + position.height = (2.0f * n + 1) / image.size.height; position.width = length; return position; @@ -107,7 +167,7 @@ DashPatternTexture::DashPatternTexture(const std::vector& from_, const std::vector& to_, const LinePatternCap cap) { const bool patternsIdentical = from_ == to_; - const int32_t patternHeight = cap == LinePatternCap::Round ? 15 : 1; + const uint32_t patternHeight = cap == LinePatternCap::Round ? 15 : 1; const uint32_t height = (patternsIdentical ? 1 : 2) * patternHeight; // The OpenGL ES 2.0 spec, section 3.8.2 states: diff --git a/src/mbgl/geometry/line_atlas.hpp b/src/mbgl/geometry/line_atlas.hpp index 853305d138..1be7cbf073 100644 --- a/src/mbgl/geometry/line_atlas.hpp +++ b/src/mbgl/geometry/line_atlas.hpp @@ -27,6 +27,13 @@ enum class LinePatternCap : bool { Round = true, }; +struct DashRange { + float left; + float right; + bool isDash; + bool isZeroLength; +}; + class DashPatternTexture { public: DashPatternTexture(const std::vector& from, const std::vector& to, LinePatternCap); -- cgit v1.2.1 From 88da1ad6c763613fa29f055394efabd3454a7cf2 Mon Sep 17 00:00:00 2001 From: Karim Naaji Date: Thu, 13 Feb 2020 17:28:17 -0500 Subject: Whitelist render-tests/line-dasharray/zero-length-gap --- metrics/ignores/platform-all.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/metrics/ignores/platform-all.json b/metrics/ignores/platform-all.json index e9ee792f37..b53e923a9d 100644 --- a/metrics/ignores/platform-all.json +++ b/metrics/ignores/platform-all.json @@ -131,6 +131,5 @@ "render-tests/feature-state/promote-id-fill-extrusion": "https://github.com/mapbox/mapbox-gl-js/pull/9202", "render-tests/text-variable-anchor/left-top-right-buttom-offset-tile-map-mode":"https://github.com/mapbox/mapbox-gl-js/pull/9202", "render-tests/line-pattern/with-dasharray":"https://github.com/mapbox/mapbox-gl-js/pull/9189", - "render-tests/symbol-sort-key/placement-tile-boundary-right-then-left": "https://github.com/mapbox/mapbox-gl-js/pull/9054", - "render-tests/line-dasharray/zero-length-gap":"https://github.com/mapbox/mapbox-gl-js/pull/9246" + "render-tests/symbol-sort-key/placement-tile-boundary-right-then-left": "https://github.com/mapbox/mapbox-gl-js/pull/9054" } -- cgit v1.2.1 From f3f0aefeadbfc1d940496a19cdc19e836e19d963 Mon Sep 17 00:00:00 2001 From: Karim Naaji Date: Thu, 13 Feb 2020 17:54:30 -0500 Subject: Apply new baselines --- .../line-dasharray/zero-length-gap/metrics.json | 35 ++++++++++++++++++++++ metrics/binary-size/linux-clang8/metrics.json | 6 ++-- .../line-dasharray/zero-length-gap/metrics.json | 35 ++++++++++++++++++++++ .../line-dasharray/zero-length-gap/metrics.json | 35 ++++++++++++++++++++++ .../line-dasharray/zero-length-gap/metrics.json | 35 ++++++++++++++++++++++ 5 files changed, 143 insertions(+), 3 deletions(-) create mode 100644 metrics/android-render-test-runner/render-tests/line-dasharray/zero-length-gap/metrics.json create mode 100644 metrics/ios-render-test-runner/render-tests/line-dasharray/zero-length-gap/metrics.json create mode 100644 metrics/linux-clang8-release/render-tests/line-dasharray/zero-length-gap/metrics.json create mode 100644 metrics/linux-gcc8-release/render-tests/line-dasharray/zero-length-gap/metrics.json diff --git a/metrics/android-render-test-runner/render-tests/line-dasharray/zero-length-gap/metrics.json b/metrics/android-render-test-runner/render-tests/line-dasharray/zero-length-gap/metrics.json new file mode 100644 index 0000000000..32c56fe8f4 --- /dev/null +++ b/metrics/android-render-test-runner/render-tests/line-dasharray/zero-length-gap/metrics.json @@ -0,0 +1,35 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 0, + 0 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 6, + 8, + 20, + 1, + [ + 34048, + 34048 + ], + [ + 58, + 58 + ], + [ + 784, + 784 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/binary-size/linux-clang8/metrics.json b/metrics/binary-size/linux-clang8/metrics.json index 6f16bb1b15..4350e4ae36 100644 --- a/metrics/binary-size/linux-clang8/metrics.json +++ b/metrics/binary-size/linux-clang8/metrics.json @@ -3,17 +3,17 @@ [ "mbgl-glfw", "/tmp/attach/install/linux-clang8-release/bin/mbgl-glfw", - 6507720 + 6569176 ], [ "mbgl-offline", "/tmp/attach/install/linux-clang8-release/bin/mbgl-offline", - 5774024 + 5835480 ], [ "mbgl-render", "/tmp/attach/install/linux-clang8-release/bin/mbgl-render", - 6409144 + 6470600 ] ] } \ No newline at end of file diff --git a/metrics/ios-render-test-runner/render-tests/line-dasharray/zero-length-gap/metrics.json b/metrics/ios-render-test-runner/render-tests/line-dasharray/zero-length-gap/metrics.json new file mode 100644 index 0000000000..32c56fe8f4 --- /dev/null +++ b/metrics/ios-render-test-runner/render-tests/line-dasharray/zero-length-gap/metrics.json @@ -0,0 +1,35 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 0, + 0 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 6, + 8, + 20, + 1, + [ + 34048, + 34048 + ], + [ + 58, + 58 + ], + [ + 784, + 784 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-clang8-release/render-tests/line-dasharray/zero-length-gap/metrics.json b/metrics/linux-clang8-release/render-tests/line-dasharray/zero-length-gap/metrics.json new file mode 100644 index 0000000000..32c56fe8f4 --- /dev/null +++ b/metrics/linux-clang8-release/render-tests/line-dasharray/zero-length-gap/metrics.json @@ -0,0 +1,35 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 0, + 0 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 6, + 8, + 20, + 1, + [ + 34048, + 34048 + ], + [ + 58, + 58 + ], + [ + 784, + 784 + ] + ] + ] +} \ No newline at end of file diff --git a/metrics/linux-gcc8-release/render-tests/line-dasharray/zero-length-gap/metrics.json b/metrics/linux-gcc8-release/render-tests/line-dasharray/zero-length-gap/metrics.json new file mode 100644 index 0000000000..32c56fe8f4 --- /dev/null +++ b/metrics/linux-gcc8-release/render-tests/line-dasharray/zero-length-gap/metrics.json @@ -0,0 +1,35 @@ +{ + "network": [ + [ + "probeNetwork - default - end", + 0, + 0 + ], + [ + "probeNetwork - default - start", + 0, + 0 + ] + ], + "gfx": [ + [ + "probeGFX - default - end", + 6, + 8, + 20, + 1, + [ + 34048, + 34048 + ], + [ + 58, + 58 + ], + [ + 784, + 784 + ] + ] + ] +} \ No newline at end of file -- cgit v1.2.1 From 189ed4aac362f7122e0889cdb9c7fc6580d24392 Mon Sep 17 00:00:00 2001 From: Karim Naaji Date: Thu, 13 Feb 2020 18:14:53 -0500 Subject: Add changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf0a476107..c51124537f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ In cases when cached resource is useable, yet don't have an expiration timestamp, we provided data to the requester from the cache and the same data was returned once 304 response was received from the network. +- [core] Fix potential visual artifact for line-dasharray ([#16202](https://github.com/mapbox/mapbox-gl-native/pull/16202)) + ### 🏁 Performance improvements - [core] Loading images to style optimization ([#16187](https://github.com/mapbox/mapbox-gl-native/pull/16187)) -- cgit v1.2.1 From a876c965a55213f38b91303c81239fbda0a9f7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Fri, 16 Aug 2019 12:03:53 +0200 Subject: [core] Store SegmentVectors in ephemeral render objects We used some shared SegmentVectors, e.g. for drawing raster or background tiles. In longer running maps, this lead to resource accumulation. By storing the SegmentVectors and the contained gfx::DrawScope objects, we ensure that resources get released when the associated render objects vanish. --- CMakeLists.txt | 2 - src/mbgl/renderer/buckets/debug_bucket.cpp | 5 +- src/mbgl/renderer/buckets/debug_bucket.hpp | 2 +- src/mbgl/renderer/buckets/raster_bucket.cpp | 14 ++-- src/mbgl/renderer/buckets/raster_bucket.hpp | 1 - .../renderer/layers/render_background_layer.cpp | 76 ++++++++++---------- .../renderer/layers/render_background_layer.hpp | 2 + src/mbgl/renderer/layers/render_circle_layer.cpp | 7 +- .../layers/render_fill_extrusion_layer.cpp | 7 +- src/mbgl/renderer/layers/render_fill_layer.cpp | 7 +- src/mbgl/renderer/layers/render_heatmap_layer.cpp | 22 +++--- src/mbgl/renderer/layers/render_heatmap_layer.hpp | 9 +-- .../renderer/layers/render_hillshade_layer.cpp | 80 +++++++++++----------- src/mbgl/renderer/layers/render_line_layer.cpp | 9 ++- src/mbgl/renderer/layers/render_raster_layer.cpp | 43 ++++++------ src/mbgl/renderer/layers/render_symbol_layer.cpp | 14 ++-- src/mbgl/renderer/paint_parameters.cpp | 57 +++++++-------- src/mbgl/renderer/render_static_data.cpp | 34 +++++++-- src/mbgl/renderer/render_static_data.hpp | 10 +-- src/mbgl/renderer/render_tile.cpp | 67 +++++++----------- src/mbgl/renderer/sources/render_image_source.cpp | 46 +++++-------- src/mbgl/util/id.cpp | 14 ---- src/mbgl/util/id.hpp | 11 --- 23 files changed, 250 insertions(+), 289 deletions(-) delete mode 100644 src/mbgl/util/id.cpp delete mode 100644 src/mbgl/util/id.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4509f08e73..485ced04aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -772,8 +772,6 @@ add_library( ${PROJECT_SOURCE_DIR}/src/mbgl/util/http_timeout.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/i18n.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/i18n.hpp - ${PROJECT_SOURCE_DIR}/src/mbgl/util/id.cpp - ${PROJECT_SOURCE_DIR}/src/mbgl/util/id.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/interpolate.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/intersection_tests.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/util/intersection_tests.hpp diff --git a/src/mbgl/renderer/buckets/debug_bucket.cpp b/src/mbgl/renderer/buckets/debug_bucket.cpp index 13380c0905..fcdc727f4b 100644 --- a/src/mbgl/renderer/buckets/debug_bucket.cpp +++ b/src/mbgl/renderer/buckets/debug_bucket.cpp @@ -2,7 +2,6 @@ #include #include #include -#include #include #include @@ -20,9 +19,7 @@ DebugBucket::DebugBucket(const OverscaledTileID& id, complete(complete_), modified(std::move(modified_)), expires(std::move(expires_)), - debugMode(debugMode_), - drawScopeID("__debug/" + util::toHex(util::nextID())) { - + debugMode(debugMode_) { auto addText = [&] (const std::string& text, double left, double baseline, double scale) { for (uint8_t c : text) { if (c < 32 || c >= 127) diff --git a/src/mbgl/renderer/buckets/debug_bucket.hpp b/src/mbgl/renderer/buckets/debug_bucket.hpp index 2b735b4987..78b1cbb8ff 100644 --- a/src/mbgl/renderer/buckets/debug_bucket.hpp +++ b/src/mbgl/renderer/buckets/debug_bucket.hpp @@ -40,9 +40,9 @@ public: gfx::IndexVector indices; SegmentVector segments; + SegmentVector tileBorderSegments; optional> vertexBuffer; optional indexBuffer; - const std::string drawScopeID; }; } // namespace mbgl diff --git a/src/mbgl/renderer/buckets/raster_bucket.cpp b/src/mbgl/renderer/buckets/raster_bucket.cpp index a26b9a5065..859ee8d2a2 100644 --- a/src/mbgl/renderer/buckets/raster_bucket.cpp +++ b/src/mbgl/renderer/buckets/raster_bucket.cpp @@ -2,21 +2,15 @@ #include #include #include -#include namespace mbgl { using namespace style; RasterBucket::RasterBucket(PremultipliedImage&& image_) - : image(std::make_shared(std::move(image_))), - drawScopeID(util::toHex(util::nextID())) { -} + : image(std::make_shared(std::move(image_))) {} -RasterBucket::RasterBucket(std::shared_ptr image_) - : image(std::move(image_)), - drawScopeID(util::toHex(util::nextID())) { -} +RasterBucket::RasterBucket(std::shared_ptr image_) : image(std::move(image_)) {} RasterBucket::~RasterBucket() = default; @@ -27,8 +21,10 @@ void RasterBucket::upload(gfx::UploadPass& uploadPass) { if (!texture) { texture = uploadPass.createTexture(*image); } - if (!segments.empty()) { + if (!vertices.empty()) { vertexBuffer = uploadPass.createVertexBuffer(std::move(vertices)); + } + if (!indices.empty()) { indexBuffer = uploadPass.createIndexBuffer(std::move(indices)); } uploaded = true; diff --git a/src/mbgl/renderer/buckets/raster_bucket.hpp b/src/mbgl/renderer/buckets/raster_bucket.hpp index f880903167..0fa3c4299e 100644 --- a/src/mbgl/renderer/buckets/raster_bucket.hpp +++ b/src/mbgl/renderer/buckets/raster_bucket.hpp @@ -37,7 +37,6 @@ public: optional> vertexBuffer; optional indexBuffer; - const std::string drawScopeID; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp index 694addcc97..96a4c44f08 100644 --- a/src/mbgl/renderer/layers/render_background_layer.cpp +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -18,7 +17,7 @@ using namespace style; namespace { -inline const BackgroundLayer::Impl& impl(const Immutable& impl) { +inline const BackgroundLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == BackgroundLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -27,13 +26,12 @@ inline const BackgroundLayer::Impl& impl(const Immutable& im RenderBackgroundLayer::RenderBackgroundLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderBackgroundLayer::~RenderBackgroundLayer() = default; void RenderBackgroundLayer::transition(const TransitionParameters ¶meters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters ¶meters) { @@ -69,7 +67,7 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { const Properties<>::PossiblyEvaluated properties; const BackgroundProgram::Binders paintAttributeData(properties, 0); - auto draw = [&](auto& program, auto&& uniformValues, const auto& textureBindings, const UnwrappedTileID& id) { + auto draw = [&](auto& program, auto&& uniformValues, const auto& textureBindings, const uint32_t id) { const auto allUniformValues = program.computeAllUniformValues( std::move(uniformValues), paintAttributeData, @@ -88,20 +86,24 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { parameters.context, *parameters.renderPass, gfx::Triangles(), - parameters.depthModeForSublayer(0, parameters.pass == RenderPass::Opaque - ? gfx::DepthMaskType::ReadWrite - : gfx::DepthMaskType::ReadOnly), + parameters.depthModeForSublayer( + 0, + parameters.pass == RenderPass::Opaque ? gfx::DepthMaskType::ReadWrite : gfx::DepthMaskType::ReadOnly), gfx::StencilMode::disabled(), parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.tileTriangleSegments, + segments, allUniformValues, allAttributeBindings, textureBindings, - getID() + "/" + util::toString(id) - ); + util::toString(id)); }; + + if (segments.empty()) { + segments = parameters.staticData.tileTriangleSegments(); + } + const auto& evaluated = static_cast(*evaluatedProperties).evaluated; const auto& crossfade = static_cast(*evaluatedProperties).crossfade; if (!evaluated.get().to.empty()) { @@ -113,24 +115,21 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { if (!imagePosA || !imagePosB) return; + uint32_t i = 0; for (const auto& tileID : util::tileCover(parameters.state, parameters.state.getIntegerZoom())) { - draw( - parameters.programs.getBackgroundLayerPrograms().backgroundPattern, - BackgroundPatternProgram::layoutUniformValues( - parameters.matrixForTile(tileID), - evaluated.get(), - parameters.patternAtlas.getPixelSize(), - *imagePosA, - *imagePosB, - crossfade, - tileID, - parameters.state - ), - BackgroundPatternProgram::TextureBindings{ - textures::image::Value{ parameters.patternAtlas.textureBinding() }, - }, - tileID - ); + draw(parameters.programs.getBackgroundLayerPrograms().backgroundPattern, + BackgroundPatternProgram::layoutUniformValues(parameters.matrixForTile(tileID), + evaluated.get(), + parameters.patternAtlas.getPixelSize(), + *imagePosA, + *imagePosB, + crossfade, + tileID, + parameters.state), + BackgroundPatternProgram::TextureBindings{ + textures::image::Value{parameters.patternAtlas.textureBinding()}, + }, + i++); } } else { auto backgroundRenderPass = (evaluated.get().a >= 1.0f @@ -139,17 +138,16 @@ void RenderBackgroundLayer::render(PaintParameters& parameters) { if (parameters.pass != backgroundRenderPass) { return; } + uint32_t i = 0; for (const auto& tileID : util::tileCover(parameters.state, parameters.state.getIntegerZoom())) { - draw( - parameters.programs.getBackgroundLayerPrograms().background, - BackgroundProgram::LayoutUniformValues { - uniforms::matrix::Value( parameters.matrixForTile(tileID) ), - uniforms::color::Value( evaluated.get() ), - uniforms::opacity::Value( evaluated.get() ), - }, - BackgroundProgram::TextureBindings{}, - tileID - ); + draw(parameters.programs.getBackgroundLayerPrograms().background, + BackgroundProgram::LayoutUniformValues{ + uniforms::matrix::Value(parameters.matrixForTile(tileID)), + uniforms::color::Value(evaluated.get()), + uniforms::opacity::Value(evaluated.get()), + }, + BackgroundProgram::TextureBindings{}, + i++); } } } diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp index dfc2adf76e..dab733172b 100644 --- a/src/mbgl/renderer/layers/render_background_layer.hpp +++ b/src/mbgl/renderer/layers/render_background_layer.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -22,6 +23,7 @@ private: // Paint properties style::BackgroundPaintProperties::Unevaluated unevaluated; + SegmentVector segments; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp index b88a026e11..e5d7e6230e 100644 --- a/src/mbgl/renderer/layers/render_circle_layer.cpp +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -17,7 +17,7 @@ using namespace style; namespace { -inline const style::CircleLayer::Impl& impl(const Immutable& impl) { +inline const style::CircleLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == CircleLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -26,11 +26,10 @@ inline const style::CircleLayer::Impl& impl(const Immutable& RenderCircleLayer::RenderCircleLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} void RenderCircleLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp index af0bc788d0..4eaec6e55f 100644 --- a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -23,7 +23,7 @@ using namespace style; namespace { -inline const FillExtrusionLayer::Impl& impl(const Immutable& impl) { +inline const FillExtrusionLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == FillExtrusionLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -32,13 +32,12 @@ inline const FillExtrusionLayer::Impl& impl(const Immutable& RenderFillExtrusionLayer::RenderFillExtrusionLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderFillExtrusionLayer::~RenderFillExtrusionLayer() = default; void RenderFillExtrusionLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp index bbfcef7aba..31b847b6a7 100644 --- a/src/mbgl/renderer/layers/render_fill_layer.cpp +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -24,7 +24,7 @@ using namespace style; namespace { -inline const FillLayer::Impl& impl(const Immutable& impl) { +inline const FillLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == FillLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -33,13 +33,12 @@ inline const FillLayer::Impl& impl(const Immutable& impl) { RenderFillLayer::RenderFillLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderFillLayer::~RenderFillLayer() = default; void RenderFillLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.cpp b/src/mbgl/renderer/layers/render_heatmap_layer.cpp index 797aedd297..5f3c36e440 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.cpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -21,7 +20,7 @@ using namespace style; namespace { -inline const HeatmapLayer::Impl& impl(const Immutable& impl) { +inline const HeatmapLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == HeatmapLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -30,13 +29,13 @@ inline const HeatmapLayer::Impl& impl(const Immutable& impl) { RenderHeatmapLayer::RenderHeatmapLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()), colorRamp({256, 1}) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()), + colorRamp({256, 1}) {} RenderHeatmapLayer::~RenderHeatmapLayer() = default; void RenderHeatmapLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); updateColorRamp(); } @@ -177,6 +176,10 @@ void RenderHeatmapLayer::render(PaintParameters& parameters) { checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); + if (segments.empty()) { + // Copy over the segments so that we can create our own DrawScopes. + segments = parameters.staticData.heatmapTextureSegments(); + } programInstance.draw( parameters.context, *parameters.renderPass, @@ -186,15 +189,14 @@ void RenderHeatmapLayer::render(PaintParameters& parameters) { parameters.colorModeForRenderPass(), gfx::CullFaceMode::disabled(), *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.heatmapTextureSegments, + segments, allUniformValues, allAttributeBindings, HeatmapTextureProgram::TextureBindings{ - textures::image::Value{ renderTexture->getTexture().getResource(), gfx::TextureFilterType::Linear }, - textures::color_ramp::Value{ colorRampTexture->getResource(), gfx::TextureFilterType::Linear }, + textures::image::Value{renderTexture->getTexture().getResource(), gfx::TextureFilterType::Linear}, + textures::color_ramp::Value{colorRampTexture->getResource(), gfx::TextureFilterType::Linear}, }, - getID() - ); + getID()); } } diff --git a/src/mbgl/renderer/layers/render_heatmap_layer.hpp b/src/mbgl/renderer/layers/render_heatmap_layer.hpp index 1e9b1063ae..b7a03a6ba5 100644 --- a/src/mbgl/renderer/layers/render_heatmap_layer.hpp +++ b/src/mbgl/renderer/layers/render_heatmap_layer.hpp @@ -1,10 +1,11 @@ #pragma once +#include +#include +#include #include #include #include -#include -#include #include namespace mbgl { @@ -24,14 +25,14 @@ private: bool queryIntersectsFeature(const GeometryCoordinates&, const GeometryTileFeature&, const float, const TransformState&, const float, const mat4&, const FeatureState&) const override; + void updateColorRamp(); // Paint properties style::HeatmapPaintProperties::Unevaluated unevaluated; PremultipliedImage colorRamp; std::unique_ptr renderTexture; optional colorRampTexture; - - void updateColorRamp(); + SegmentVector segments; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_hillshade_layer.cpp b/src/mbgl/renderer/layers/render_hillshade_layer.cpp index b570d9c4c9..bf899221f8 100644 --- a/src/mbgl/renderer/layers/render_hillshade_layer.cpp +++ b/src/mbgl/renderer/layers/render_hillshade_layer.cpp @@ -20,7 +20,7 @@ using namespace style; namespace { -inline const HillshadeLayer::Impl& impl(const Immutable& impl) { +inline const HillshadeLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == HillshadeLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -29,8 +29,7 @@ inline const HillshadeLayer::Impl& impl(const Immutable& imp RenderHillshadeLayer::RenderHillshadeLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderHillshadeLayer::~RenderHillshadeLayer() = default; @@ -48,7 +47,7 @@ const std::array RenderHillshadeLayer::getLight(const PaintParameters& } void RenderHillshadeLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderHillshadeLayer::evaluate(const PropertyEvaluationParameters& parameters) { @@ -111,21 +110,19 @@ void RenderHillshadeLayer::render(PaintParameters& parameters) { checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); - programInstance.draw( - parameters.context, - *parameters.renderPass, - gfx::Triangles(), - parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), - gfx::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - indexBuffer, - segments, - allUniformValues, - allAttributeBindings, - textureBindings, - getID() + "/" + util::toString(id) - ); + programInstance.draw(parameters.context, + *parameters.renderPass, + gfx::Triangles(), + parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), + gfx::StencilMode::disabled(), + parameters.colorModeForRenderPass(), + gfx::CullFaceMode::disabled(), + indexBuffer, + segments, + allUniformValues, + allAttributeBindings, + textureBindings, + getID()); }; mat4 mat; @@ -177,29 +174,30 @@ void RenderHillshadeLayer::render(PaintParameters& parameters) { checkRenderability(parameters, programInstance.activeBindingCount(allAttributeBindings)); - programInstance.draw( - parameters.context, - *renderPass, - gfx::Triangles(), - parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), - gfx::StencilMode::disabled(), - parameters.colorModeForRenderPass(), - gfx::CullFaceMode::disabled(), - *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.rasterSegments, - allUniformValues, - allAttributeBindings, - HillshadePrepareProgram::TextureBindings{ - textures::image::Value{ bucket.dem->getResource() }, - }, - getID() + "/p/" + util::toString(tile.id) - ); + // Copy over the segments so that we can create our own DrawScopes that get destroyed + // after this draw call. + auto segments = parameters.staticData.rasterSegments(); + programInstance.draw(parameters.context, + *renderPass, + gfx::Triangles(), + parameters.depthModeForSublayer(0, gfx::DepthMaskType::ReadOnly), + gfx::StencilMode::disabled(), + parameters.colorModeForRenderPass(), + gfx::CullFaceMode::disabled(), + *parameters.staticData.quadTriangleIndexBuffer, + segments, + allUniformValues, + allAttributeBindings, + HillshadePrepareProgram::TextureBindings{ + textures::image::Value{bucket.dem->getResource()}, + }, + "prepare"); bucket.texture = std::move(view->getTexture()); bucket.setPrepared(true); } else if (parameters.pass == RenderPass::Translucent) { assert(bucket.texture); - if (bucket.vertexBuffer && bucket.indexBuffer && !bucket.segments.empty()) { + if (bucket.vertexBuffer && bucket.indexBuffer) { // Draw only the parts of the tile that aren't drawn by another tile in the layer. draw(parameters.matrixForTile(tile.id, true), *bucket.vertexBuffer, @@ -211,13 +209,17 @@ void RenderHillshadeLayer::render(PaintParameters& parameters) { }); } else { // Draw the full tile. + if (bucket.segments.empty()) { + // Copy over the segments so that we can create our own DrawScopes. + bucket.segments = parameters.staticData.rasterSegments(); + } draw(parameters.matrixForTile(tile.id, true), *parameters.staticData.rasterVertexBuffer, *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.rasterSegments, + bucket.segments, tile.id, HillshadeProgram::TextureBindings{ - textures::image::Value{ bucket.texture->getResource(), gfx::TextureFilterType::Linear }, + textures::image::Value{bucket.texture->getResource(), gfx::TextureFilterType::Linear}, }); } } diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp index 588cf6286c..90bb38b9f9 100644 --- a/src/mbgl/renderer/layers/render_line_layer.cpp +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -23,7 +23,7 @@ using namespace style; namespace { -inline const LineLayer::Impl& impl(const Immutable& impl) { +inline const LineLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == LineLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -32,14 +32,13 @@ inline const LineLayer::Impl& impl(const Immutable& impl) { RenderLineLayer::RenderLineLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()), - colorRamp({256, 1}) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()), + colorRamp({256, 1}) {} RenderLineLayer::~RenderLineLayer() = default; void RenderLineLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); updateColorRamp(); } diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index 8a1a8a6c28..047333d5e5 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -16,7 +16,7 @@ using namespace style; namespace { -inline const RasterLayer::Impl& impl(const Immutable& impl) { +inline const RasterLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == RasterLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -25,13 +25,12 @@ inline const RasterLayer::Impl& impl(const Immutable& impl) RenderRasterLayer::RenderRasterLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderRasterLayer::~RenderRasterLayer() = default; void RenderRasterLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); } void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) { @@ -153,14 +152,14 @@ void RenderRasterLayer::render(PaintParameters& parameters) { size_t i = 0; for (const auto& matrix_ : imageData->matrices) { draw(matrix_, - *bucket.vertexBuffer, - *bucket.indexBuffer, - bucket.segments, - RasterProgram::TextureBindings{ - textures::image0::Value{ bucket.texture->getResource(), filter }, - textures::image1::Value{ bucket.texture->getResource(), filter }, - }, - bucket.drawScopeID + std::to_string(i++)); + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.segments, + RasterProgram::TextureBindings{ + textures::image0::Value{bucket.texture->getResource(), filter}, + textures::image1::Value{bucket.texture->getResource(), filter}, + }, + std::to_string(i++)); } } else if (renderTiles) { for (const RenderTile& tile : *renderTiles) { @@ -174,28 +173,32 @@ void RenderRasterLayer::render(PaintParameters& parameters) { continue; assert(bucket.texture); - if (bucket.vertexBuffer && bucket.indexBuffer && !bucket.segments.empty()) { + if (bucket.vertexBuffer && bucket.indexBuffer) { // Draw only the parts of the tile that aren't drawn by another tile in the layer. draw(parameters.matrixForTile(tile.id, true), *bucket.vertexBuffer, *bucket.indexBuffer, bucket.segments, RasterProgram::TextureBindings{ - textures::image0::Value{ bucket.texture->getResource(), filter }, - textures::image1::Value{ bucket.texture->getResource(), filter }, + textures::image0::Value{bucket.texture->getResource(), filter}, + textures::image1::Value{bucket.texture->getResource(), filter}, }, - bucket.drawScopeID); + "image"); } else { // Draw the full tile. + if (bucket.segments.empty()) { + // Copy over the segments so that we can create our own DrawScopes. + bucket.segments = parameters.staticData.rasterSegments(); + } draw(parameters.matrixForTile(tile.id, true), *parameters.staticData.rasterVertexBuffer, *parameters.staticData.quadTriangleIndexBuffer, - parameters.staticData.rasterSegments, + bucket.segments, RasterProgram::TextureBindings{ - textures::image0::Value{ bucket.texture->getResource(), filter }, - textures::image1::Value{ bucket.texture->getResource(), filter }, + textures::image0::Value{bucket.texture->getResource(), filter}, + textures::image1::Value{bucket.texture->getResource(), filter}, }, - bucket.drawScopeID); + "image"); } } } diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp index 955ad2ce51..2a94c452c7 100644 --- a/src/mbgl/renderer/layers/render_symbol_layer.cpp +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -290,7 +290,7 @@ void drawText(const DrawFn& draw, } } -inline const SymbolLayer::Impl& impl(const Immutable& impl) { +inline const SymbolLayer::Impl& impl_cast(const Immutable& impl) { assert(impl->getTypeInfo() == SymbolLayer::Impl::staticTypeInfo()); return static_cast(*impl); } @@ -299,14 +299,14 @@ inline const SymbolLayer::Impl& impl(const Immutable& impl) RenderSymbolLayer::RenderSymbolLayer(Immutable _impl) : RenderLayer(makeMutable(std::move(_impl))), - unevaluated(impl(baseImpl).paint.untransitioned()) { -} + unevaluated(impl_cast(baseImpl).paint.untransitioned()) {} RenderSymbolLayer::~RenderSymbolLayer() = default; void RenderSymbolLayer::transition(const TransitionParameters& parameters) { - unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); - hasFormatSectionOverrides = SymbolLayerPaintPropertyOverrides::hasOverrides(impl(baseImpl).layout.get()); + unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated)); + hasFormatSectionOverrides = + SymbolLayerPaintPropertyOverrides::hasOverrides(impl_cast(baseImpl).layout.get()); } void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) { @@ -314,7 +314,7 @@ void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) staticImmutableCast(baseImpl), unevaluated.evaluate(parameters)); auto& evaluated = properties->evaluated; - auto& layout = impl(baseImpl).layout; + auto& layout = impl_cast(baseImpl).layout; if (hasFormatSectionOverrides) { SymbolLayerPaintPropertyOverrides::setOverrides(layout, evaluated); @@ -346,7 +346,7 @@ void RenderSymbolLayer::render(PaintParameters& parameters) { return; } - const bool sortFeaturesByKey = !impl(baseImpl).layout.get().isUndefined(); + const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get().isUndefined(); std::multiset renderableSegments; const auto draw = [¶meters, this] (auto& programInstance, diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index 6c6abc008b..b2f958b14e 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -129,39 +129,30 @@ void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) { const int32_t stencilID = nextStencilID++; tileClippingMaskIDs.emplace(renderTile.id, stencilID); - program.draw( - context, - *renderPass, - gfx::Triangles(), - gfx::DepthMode::disabled(), - gfx::StencilMode { - gfx::StencilMode::Always{}, - stencilID, - 0b11111111, - gfx::StencilOpType::Keep, - gfx::StencilOpType::Keep, - gfx::StencilOpType::Replace - }, - gfx::ColorMode::disabled(), - gfx::CullFaceMode::disabled(), - *staticData.quadTriangleIndexBuffer, - staticData.tileTriangleSegments, - program.computeAllUniformValues( - ClippingMaskProgram::LayoutUniformValues { - uniforms::matrix::Value( matrixForTile(renderTile.id) ), - }, - paintAttributeData, - properties, - state.getZoom() - ), - program.computeAllAttributeBindings( - *staticData.tileVertexBuffer, - paintAttributeData, - properties - ), - ClippingMaskProgram::TextureBindings{}, - "clipping/" + util::toString(stencilID) - ); + program.draw(context, + *renderPass, + gfx::Triangles(), + gfx::DepthMode::disabled(), + gfx::StencilMode{gfx::StencilMode::Always{}, + stencilID, + 0b11111111, + gfx::StencilOpType::Keep, + gfx::StencilOpType::Keep, + gfx::StencilOpType::Replace}, + gfx::ColorMode::disabled(), + gfx::CullFaceMode::disabled(), + *staticData.quadTriangleIndexBuffer, + staticData.clippingMaskSegments, + program.computeAllUniformValues( + ClippingMaskProgram::LayoutUniformValues{ + uniforms::matrix::Value(matrixForTile(renderTile.id)), + }, + paintAttributeData, + properties, + state.getZoom()), + program.computeAllAttributeBindings(*staticData.tileVertexBuffer, paintAttributeData, properties), + ClippingMaskProgram::TextureBindings{}, + "clipping/" + util::toString(stencilID)); } } diff --git a/src/mbgl/renderer/render_static_data.cpp b/src/mbgl/renderer/render_static_data.cpp index 6378ad9989..f7d9c18a78 100644 --- a/src/mbgl/renderer/render_static_data.cpp +++ b/src/mbgl/renderer/render_static_data.cpp @@ -50,15 +50,37 @@ static gfx::VertexVector heatmapTextureVertices() { } RenderStaticData::RenderStaticData(gfx::Context& context, float pixelRatio) - : programs(context, ProgramParameters { pixelRatio, false }) + : programs(context, ProgramParameters{pixelRatio, false}), + clippingMaskSegments(tileTriangleSegments()) #ifndef NDEBUG - , overdrawPrograms(context, ProgramParameters { pixelRatio, true }) + , + overdrawPrograms(context, ProgramParameters{pixelRatio, true}) #endif { - tileTriangleSegments.emplace_back(0, 0, 4, 6); - tileBorderSegments.emplace_back(0, 0, 4, 5); - rasterSegments.emplace_back(0, 0, 4, 6); - heatmapTextureSegments.emplace_back(0, 0, 4, 6); +} + +SegmentVector RenderStaticData::tileTriangleSegments() { + SegmentVector segments; + segments.emplace_back(0, 0, 4, 6); + return segments; +} + +SegmentVector RenderStaticData::tileBorderSegments() { + SegmentVector segments; + segments.emplace_back(0, 0, 4, 5); + return segments; +} + +SegmentVector RenderStaticData::rasterSegments() { + SegmentVector segments; + segments.emplace_back(0, 0, 4, 6); + return segments; +} + +SegmentVector RenderStaticData::heatmapTextureSegments() { + SegmentVector segments; + segments.emplace_back(0, 0, 4, 6); + return segments; } void RenderStaticData::upload(gfx::UploadPass& uploadPass) { diff --git a/src/mbgl/renderer/render_static_data.hpp b/src/mbgl/renderer/render_static_data.hpp index 6bf2c846f4..22b29387db 100644 --- a/src/mbgl/renderer/render_static_data.hpp +++ b/src/mbgl/renderer/render_static_data.hpp @@ -30,10 +30,10 @@ public: optional quadTriangleIndexBuffer; optional tileBorderIndexBuffer; - SegmentVector tileTriangleSegments; - SegmentVector tileBorderSegments; - SegmentVector rasterSegments; - SegmentVector heatmapTextureSegments; + static SegmentVector tileTriangleSegments(); + static SegmentVector tileBorderSegments(); + static SegmentVector rasterSegments(); + static SegmentVector heatmapTextureSegments(); optional> depthRenderbuffer; bool has3D = false; @@ -42,6 +42,8 @@ public: Programs programs; + const SegmentVector clippingMaskSegments; + #ifndef NDEBUG Programs overdrawPrograms; #endif diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp index 70db10fa08..ce5fef05b8 100644 --- a/src/mbgl/renderer/render_tile.cpp +++ b/src/mbgl/renderer/render_tile.cpp @@ -147,81 +147,66 @@ void RenderTile::finishRender(PaintParameters& parameters) const { program.draw( parameters.context, *parameters.renderPass, - gfx::Lines { 4.0f * parameters.pixelRatio }, + gfx::Lines{4.0f * parameters.pixelRatio}, gfx::DepthMode::disabled(), gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *debugBucket->indexBuffer, debugBucket->segments, - program.computeAllUniformValues( - DebugProgram::LayoutUniformValues { - uniforms::matrix::Value( matrix ), - uniforms::color::Value( Color::white() ) - }, - paintAttributeData, - properties, - parameters.state.getZoom() - ), + program.computeAllUniformValues(DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), + uniforms::color::Value(Color::white())}, + paintAttributeData, + properties, + parameters.state.getZoom()), allAttributeBindings, DebugProgram::TextureBindings{}, - "__debug/" + debugBucket->drawScopeID + "/text-outline" - ); + "text-outline"); program.draw( parameters.context, *parameters.renderPass, - gfx::Lines { 2.0f * parameters.pixelRatio }, + gfx::Lines{2.0f * parameters.pixelRatio}, gfx::DepthMode::disabled(), gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *debugBucket->indexBuffer, debugBucket->segments, - program.computeAllUniformValues( - DebugProgram::LayoutUniformValues { - uniforms::matrix::Value( matrix ), - uniforms::color::Value( Color::black() ) - }, - paintAttributeData, - properties, - parameters.state.getZoom() - ), + program.computeAllUniformValues(DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), + uniforms::color::Value(Color::black())}, + paintAttributeData, + properties, + parameters.state.getZoom()), allAttributeBindings, DebugProgram::TextureBindings{}, - "__debug/" + debugBucket->drawScopeID + "/text" - ); + "text"); } if (parameters.debugOptions & MapDebugOptions::TileBorders) { assert(debugBucket); + if (debugBucket->tileBorderSegments.empty()) { + debugBucket->tileBorderSegments = parameters.staticData.tileBorderSegments(); + } parameters.programs.debug.draw( parameters.context, *parameters.renderPass, - gfx::LineStrip { 4.0f * parameters.pixelRatio }, + gfx::LineStrip{4.0f * parameters.pixelRatio}, gfx::DepthMode::disabled(), gfx::StencilMode::disabled(), gfx::ColorMode::unblended(), gfx::CullFaceMode::disabled(), *parameters.staticData.tileBorderIndexBuffer, - parameters.staticData.tileBorderSegments, - program.computeAllUniformValues( - DebugProgram::LayoutUniformValues { - uniforms::matrix::Value( matrix ), - uniforms::color::Value( Color::red() ) - }, - paintAttributeData, - properties, - parameters.state.getZoom() - ), + debugBucket->tileBorderSegments, + program.computeAllUniformValues(DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), + uniforms::color::Value(Color::red())}, + paintAttributeData, + properties, + parameters.state.getZoom()), program.computeAllAttributeBindings( - *parameters.staticData.tileVertexBuffer, - paintAttributeData, - properties - ), + *parameters.staticData.tileVertexBuffer, paintAttributeData, properties), DebugProgram::TextureBindings{}, - "__debug/" + debugBucket->drawScopeID - ); + "border"); } } diff --git a/src/mbgl/renderer/sources/render_image_source.cpp b/src/mbgl/renderer/sources/render_image_source.cpp index 6d197df9db..30f1bbcee6 100644 --- a/src/mbgl/renderer/sources/render_image_source.cpp +++ b/src/mbgl/renderer/sources/render_image_source.cpp @@ -36,33 +36,25 @@ void ImageSourceRenderData::render(PaintParameters& parameters) const { auto& programInstance = parameters.programs.debug; for (auto matrix : matrices) { - programInstance.draw( - parameters.context, - *parameters.renderPass, - gfx::LineStrip { 4.0f * parameters.pixelRatio }, - gfx::DepthMode::disabled(), - gfx::StencilMode::disabled(), - gfx::ColorMode::unblended(), - gfx::CullFaceMode::disabled(), - *parameters.staticData.tileBorderIndexBuffer, - parameters.staticData.tileBorderSegments, - programInstance.computeAllUniformValues( - DebugProgram::LayoutUniformValues { - uniforms::matrix::Value( matrix ), - uniforms::color::Value( Color::red() ) - }, - paintAttributeData, - properties, - parameters.state.getZoom() - ), - programInstance.computeAllAttributeBindings( - *parameters.staticData.tileVertexBuffer, - paintAttributeData, - properties - ), - DebugProgram::TextureBindings{}, - "image" - ); + programInstance.draw(parameters.context, + *parameters.renderPass, + gfx::LineStrip{4.0f * parameters.pixelRatio}, + gfx::DepthMode::disabled(), + gfx::StencilMode::disabled(), + gfx::ColorMode::unblended(), + gfx::CullFaceMode::disabled(), + *parameters.staticData.tileBorderIndexBuffer, + parameters.staticData.tileBorderSegments(), + programInstance.computeAllUniformValues( + DebugProgram::LayoutUniformValues{uniforms::matrix::Value(matrix), + uniforms::color::Value(Color::red())}, + paintAttributeData, + properties, + parameters.state.getZoom()), + programInstance.computeAllAttributeBindings( + *parameters.staticData.tileVertexBuffer, paintAttributeData, properties), + DebugProgram::TextureBindings{}, + "image"); } } diff --git a/src/mbgl/util/id.cpp b/src/mbgl/util/id.cpp deleted file mode 100644 index 4486194de4..0000000000 --- a/src/mbgl/util/id.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include - -#include - -namespace mbgl { -namespace util { - -uint64_t nextID() { - static std::atomic GUID { 0 }; - return GUID++; -} - -} // namespace util -} // namespace mbgl diff --git a/src/mbgl/util/id.hpp b/src/mbgl/util/id.hpp deleted file mode 100644 index 12e23dfc2d..0000000000 --- a/src/mbgl/util/id.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -namespace mbgl { -namespace util { - -uint64_t nextID(); - -} // namespace util -} // namespace mbgl -- cgit v1.2.1 From 9e1457276281baeb92ff33e2aee3418db172f218 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Thu, 13 Feb 2020 19:05:25 +0200 Subject: [core] Update baselines --- metrics/binary-size/linux-clang8/metrics.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metrics/binary-size/linux-clang8/metrics.json b/metrics/binary-size/linux-clang8/metrics.json index 4350e4ae36..067acd3306 100644 --- a/metrics/binary-size/linux-clang8/metrics.json +++ b/metrics/binary-size/linux-clang8/metrics.json @@ -16,4 +16,4 @@ 6470600 ] ] -} \ No newline at end of file +} -- cgit v1.2.1 From 59294aaef333bdd455bd13d6bab6fca730379b52 Mon Sep 17 00:00:00 2001 From: Alexander Shalamov Date: Thu, 13 Feb 2020 21:53:16 +0200 Subject: [core] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c51124537f..fb643dd222 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,10 @@ - [core] Fix potential visual artifact for line-dasharray ([#16202](https://github.com/mapbox/mapbox-gl-native/pull/16202)) +- Store gfx::DrawScope objects with associated render objects. ([#15395](https://github.com/mapbox/mapbox-gl-native/pull/15395)) + + We used some shared SegmentVectors, e.g. for drawing raster or background tiles. In longer running maps, this lead to resource accumulation. By storing the SegmentVectors and the contained gfx::DrawScope objects, we ensure that resources get released when the associated render objects vanish. + ### 🏁 Performance improvements - [core] Loading images to style optimization ([#16187](https://github.com/mapbox/mapbox-gl-native/pull/16187)) -- cgit v1.2.1