summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md16
-rw-r--r--CMakeLists.txt22
-rw-r--r--circle.yml99
-rw-r--r--metrics/android-render-test-runner/render-tests/line-dasharray/zero-length-gap/metrics.json35
-rw-r--r--metrics/binary-size/linux-clang8/metrics.json8
-rw-r--r--metrics/ignores/platform-all.json3
-rw-r--r--metrics/ios-render-test-runner/render-tests/line-dasharray/zero-length-gap/metrics.json35
-rw-r--r--metrics/linux-clang8-release/render-tests/line-dasharray/zero-length-gap/metrics.json35
-rw-r--r--metrics/linux-gcc8-release/render-tests/line-dasharray/zero-length-gap/metrics.json35
-rw-r--r--platform/default/src/mbgl/storage/main_resource_loader.cpp6
-rw-r--r--platform/ios/ios.cmake122
-rw-r--r--platform/ios/test/common/AppDelegate.h (renamed from render-test/ios/AppDelegate.h)0
-rw-r--r--platform/ios/test/common/AppDelegate.m (renamed from render-test/ios/AppDelegate.m)0
-rw-r--r--platform/ios/test/common/LaunchScreen.storyboard (renamed from render-test/ios/LaunchScreen.storyboard)0
-rw-r--r--platform/ios/test/common/Main.storyboard (renamed from render-test/ios/Main.storyboard)0
-rw-r--r--platform/ios/test/common/Tests.m37
-rw-r--r--platform/ios/test/common/ViewController.h (renamed from render-test/ios/ViewController.h)0
-rw-r--r--platform/ios/test/common/ViewController.m (renamed from render-test/ios/ViewController.m)0
-rw-r--r--platform/ios/test/common/ios_test_runner.hpp (renamed from render-test/ios/ios_test_runner.hpp)2
-rw-r--r--platform/ios/test/common/main.m9
-rw-r--r--render-test/ios/Gemfile3
-rw-r--r--render-test/ios/Gemfile.lock159
-rw-r--r--scripts/ci/ccache-c.in9
-rw-r--r--scripts/ci/ccache-cxx.in9
-rw-r--r--src/mbgl/geometry/line_atlas.cpp178
-rw-r--r--src/mbgl/geometry/line_atlas.hpp7
-rw-r--r--src/mbgl/renderer/buckets/debug_bucket.cpp5
-rw-r--r--src/mbgl/renderer/buckets/debug_bucket.hpp2
-rw-r--r--src/mbgl/renderer/buckets/raster_bucket.cpp14
-rw-r--r--src/mbgl/renderer/buckets/raster_bucket.hpp1
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.cpp76
-rw-r--r--src/mbgl/renderer/layers/render_background_layer.hpp2
-rw-r--r--src/mbgl/renderer/layers/render_circle_layer.cpp7
-rw-r--r--src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp7
-rw-r--r--src/mbgl/renderer/layers/render_fill_layer.cpp7
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.cpp22
-rw-r--r--src/mbgl/renderer/layers/render_heatmap_layer.hpp9
-rw-r--r--src/mbgl/renderer/layers/render_hillshade_layer.cpp80
-rw-r--r--src/mbgl/renderer/layers/render_line_layer.cpp9
-rw-r--r--src/mbgl/renderer/layers/render_raster_layer.cpp43
-rw-r--r--src/mbgl/renderer/layers/render_symbol_layer.cpp14
-rw-r--r--src/mbgl/renderer/paint_parameters.cpp57
-rw-r--r--src/mbgl/renderer/render_static_data.cpp34
-rw-r--r--src/mbgl/renderer/render_static_data.hpp10
-rw-r--r--src/mbgl/renderer/render_tile.cpp67
-rw-r--r--src/mbgl/renderer/sources/render_image_source.cpp46
-rw-r--r--src/mbgl/sprite/sprite_loader.cpp6
-rw-r--r--src/mbgl/util/id.cpp14
-rw-r--r--src/mbgl/util/id.hpp11
-rw-r--r--test/CMakeLists.txt18
-rw-r--r--test/fixtures/local_glyphs/ping_fang/expected.pngbin18174 -> 17731 bytes
-rw-r--r--test/include/mbgl/test/util.hpp17
-rw-r--r--test/ios/Info.plist62
-rw-r--r--test/ios/README.md7
-rw-r--r--test/ios/UnitTestsApp_iphoneos13.2-arm64e-debug.xctestrun68
-rw-r--r--test/ios/UnitTestsApp_iphoneos13.2-arm64e-release.xctestrun68
-rw-r--r--test/ios/codesigning/UnitTestsApp.app.xcent.template16
-rw-r--r--test/ios/codesigning/UnitTestsAppTests.xctest.xcent.template16
-rw-r--r--test/ios/codesigning/XCTAutomationSupport.framework.xcent.template16
-rw-r--r--test/ios/codesigning/XCTest.framework.xcent.template16
-rwxr-xr-xtest/ios/codesigning/codesign_all.sh8
-rwxr-xr-xtest/ios/codesigning/generate-entitlements.swift40
-rw-r--r--test/ios/codesigning/libXCTestSwiftSupport.dylib.xcent.template16
-rw-r--r--test/ios/fastlane/Appfile3
-rw-r--r--test/ios/fastlane/Matchfile5
-rw-r--r--test/ios/iosTestRunner.h9
-rw-r--r--test/ios/iosTestRunner.mm82
-rw-r--r--test/ios/ios_test_runner.cpp31
-rw-r--r--test/ios/tests/Info.plist22
-rw-r--r--test/map/transform.test.cpp5
-rw-r--r--test/storage/main_resource_loader.test.cpp36
-rw-r--r--test/storage/offline_database.test.cpp8
-rw-r--r--test/tile/vector_tile.test.cpp2
-rw-r--r--test/util/tile_cover.test.cpp4
74 files changed, 1363 insertions, 584 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bad7958a10..fb643dd222 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,16 +26,24 @@
- [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.
+
+- [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))
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
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e008db2117..485ced04aa 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)
@@ -752,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/circle.yml b/circle.yml
index cb54ae998a..a9c10b6395 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
@@ -151,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
@@ -236,7 +242,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:
@@ -311,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:
@@ -341,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
@@ -398,6 +391,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:
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..067acd3306 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/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"
}
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
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/platform/ios/ios.cmake b/platform/ios/ios.cmake
index aa22a376f8..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)
@@ -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
- $<$<CONFIG:Debug>:YES>
- )
-
target_include_directories(
RenderTestAppTests
PUBLIC ${PROJECT_SOURCE_DIR}/render-test/ios
@@ -188,7 +179,94 @@ 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 $<$<CONFIG:Debug>: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)
+ 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}/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}/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/iosTestRunner.h
+ ${PROJECT_SOURCE_DIR}/test/ios/iosTestRunner.mm
+ ${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
+ ${PROJECT_SOURCE_DIR}/include
+ ${PROJECT_SOURCE_DIR}/platform/ios/test/common
+ ${PROJECT_SOURCE_DIR}/test/include
+ ${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}/platform/ios/test/common/Tests.m)
+
+ target_include_directories(
+ UnitTestsAppTests
+ PUBLIC ${PROJECT_SOURCE_DIR}/test/ios
+ )
+
+ 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 $<$<CONFIG:Debug>: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/render-test/ios/AppDelegate.h b/platform/ios/test/common/AppDelegate.h
index 134c8063dc..134c8063dc 100644
--- a/render-test/ios/AppDelegate.h
+++ b/platform/ios/test/common/AppDelegate.h
diff --git a/render-test/ios/AppDelegate.m b/platform/ios/test/common/AppDelegate.m
index 874d18de2a..874d18de2a 100644
--- a/render-test/ios/AppDelegate.m
+++ b/platform/ios/test/common/AppDelegate.m
diff --git a/render-test/ios/LaunchScreen.storyboard b/platform/ios/test/common/LaunchScreen.storyboard
index c9b7564332..c9b7564332 100644
--- a/render-test/ios/LaunchScreen.storyboard
+++ b/platform/ios/test/common/LaunchScreen.storyboard
diff --git a/render-test/ios/Main.storyboard b/platform/ios/test/common/Main.storyboard
index 34d4c7e2ec..34d4c7e2ec 100644
--- a/render-test/ios/Main.storyboard
+++ b/platform/ios/test/common/Main.storyboard
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 <XCTest/XCTest.h>
+#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/render-test/ios/ViewController.h b/platform/ios/test/common/ViewController.h
index 9c7dfc57ec..9c7dfc57ec 100644
--- a/render-test/ios/ViewController.h
+++ b/platform/ios/test/common/ViewController.h
diff --git a/render-test/ios/ViewController.m b/platform/ios/test/common/ViewController.m
index e9c526122a..e9c526122a 100644
--- a/render-test/ios/ViewController.m
+++ b/platform/ios/test/common/ViewController.m
diff --git a/render-test/ios/ios_test_runner.hpp b/platform/ios/test/common/ios_test_runner.hpp
index 4ec1da93b0..db263dc73c 100644
--- a/render-test/ios/ios_test_runner.hpp
+++ b/platform/ios/test/common/ios_test_runner.hpp
@@ -8,7 +8,7 @@ public:
TestRunner() = default;
~TestRunner() = default;
- bool startTest(const std::string& manifest);
+ 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 <UIKit/UIKit.h>
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[])
+{
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
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/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}" "$@"
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 <cmath>
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/gfx/upload_pass.hpp>
#include <mbgl/math/log2.hpp>
@@ -6,8 +7,6 @@
#include <mbgl/util/logging.hpp>
#include <mbgl/util/platform.hpp>
-#include <cmath>
-
namespace mbgl {
namespace {
@@ -20,82 +19,143 @@ size_t getDashPatternHash(const std::vector<float>& dasharray, const LinePattern
return key;
}
-LinePatternPos addDashPattern(AlphaImage& image,
- const int32_t yOffset,
- const std::vector<float>& dasharray,
- const LinePatternCap patternCap) {
- const uint8_t n = patternCap == LinePatternCap::Round ? 7 : 0;
- constexpr const uint8_t offset = 128;
+std::vector<DashRange> getDashRanges(const std::vector<float>& 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<DashRange> 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<DashRange>& 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<float>(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<uint8_t>(fmaxf(0.0f, fminf(255.0f, signedDistance + 128.0f)));
+ }
+ }
+}
+void addRegularDash(std::vector<DashRange>& 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<uint8_t>(fmaxf(0.0f, fminf(255.0f, signedDistance + 128.0f)));
+ }
+}
+
+LinePatternPos addDashPattern(AlphaImage& image,
+ uint32_t yOffset,
+ const std::vector<float>& 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<DashRange> 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<float>& from_,
const std::vector<float>& 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<float>& from, const std::vector<float>& to, LinePatternCap);
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 <mbgl/geometry/debug_font_data.hpp>
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/util/string.hpp>
-#include <mbgl/util/id.hpp>
#include <cmath>
#include <string>
@@ -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<gfx::Lines> indices;
SegmentVector<DebugAttributes> segments;
+ SegmentVector<DebugAttributes> tileBorderSegments;
optional<gfx::VertexBuffer<DebugLayoutVertex>> vertexBuffer;
optional<gfx::IndexBuffer> 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 <mbgl/renderer/layers/render_raster_layer.hpp>
#include <mbgl/programs/raster_program.hpp>
#include <mbgl/gfx/upload_pass.hpp>
-#include <mbgl/util/id.hpp>
namespace mbgl {
using namespace style;
RasterBucket::RasterBucket(PremultipliedImage&& image_)
- : image(std::make_shared<PremultipliedImage>(std::move(image_))),
- drawScopeID(util::toHex(util::nextID())) {
-}
+ : image(std::make_shared<PremultipliedImage>(std::move(image_))) {}
-RasterBucket::RasterBucket(std::shared_ptr<PremultipliedImage> image_)
- : image(std::move(image_)),
- drawScopeID(util::toHex(util::nextID())) {
-}
+RasterBucket::RasterBucket(std::shared_ptr<PremultipliedImage> 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<gfx::VertexBuffer<RasterLayoutVertex>> vertexBuffer;
optional<gfx::IndexBuffer> 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 <mbgl/renderer/image_manager.hpp>
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/programs/programs.hpp>
-#include <mbgl/programs/background_program.hpp>
#include <mbgl/util/tile_cover.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
@@ -18,7 +17,7 @@ using namespace style;
namespace {
-inline const BackgroundLayer::Impl& impl(const Immutable<style::Layer::Impl>& impl) {
+inline const BackgroundLayer::Impl& impl_cast(const Immutable<style::Layer::Impl>& impl) {
assert(impl->getTypeInfo() == BackgroundLayer::Impl::staticTypeInfo());
return static_cast<const style::BackgroundLayer::Impl&>(*impl);
}
@@ -27,13 +26,12 @@ inline const BackgroundLayer::Impl& impl(const Immutable<style::Layer::Impl>& im
RenderBackgroundLayer::RenderBackgroundLayer(Immutable<style::BackgroundLayer::Impl> _impl)
: RenderLayer(makeMutable<BackgroundLayerProperties>(std::move(_impl))),
- unevaluated(impl(baseImpl).paint.untransitioned()) {
-}
+ unevaluated(impl_cast(baseImpl).paint.untransitioned()) {}
RenderBackgroundLayer::~RenderBackgroundLayer() = default;
void RenderBackgroundLayer::transition(const TransitionParameters &parameters) {
- unevaluated = impl(baseImpl).paint.transitioned(parameters, std::move(unevaluated));
+ unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated));
}
void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters &parameters) {
@@ -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<const BackgroundLayerProperties&>(*evaluatedProperties).evaluated;
const auto& crossfade = static_cast<const BackgroundLayerProperties&>(*evaluatedProperties).crossfade;
if (!evaluated.get<BackgroundPattern>().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<BackgroundOpacity>(),
- 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<BackgroundOpacity>(),
+ parameters.patternAtlas.getPixelSize(),
+ *imagePosA,
+ *imagePosB,
+ crossfade,
+ tileID,
+ parameters.state),
+ BackgroundPatternProgram::TextureBindings{
+ textures::image::Value{parameters.patternAtlas.textureBinding()},
+ },
+ i++);
}
} else {
auto backgroundRenderPass = (evaluated.get<BackgroundColor>().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<BackgroundColor>() ),
- uniforms::opacity::Value( evaluated.get<BackgroundOpacity>() ),
- },
- BackgroundProgram::TextureBindings{},
- tileID
- );
+ draw(parameters.programs.getBackgroundLayerPrograms().background,
+ BackgroundProgram::LayoutUniformValues{
+ uniforms::matrix::Value(parameters.matrixForTile(tileID)),
+ uniforms::color::Value(evaluated.get<BackgroundColor>()),
+ uniforms::opacity::Value(evaluated.get<BackgroundOpacity>()),
+ },
+ 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 <mbgl/programs/background_program.hpp>
#include <mbgl/renderer/render_layer.hpp>
#include <mbgl/style/layers/background_layer_impl.hpp>
#include <mbgl/style/layers/background_layer_properties.hpp>
@@ -22,6 +23,7 @@ private:
// Paint properties
style::BackgroundPaintProperties::Unevaluated unevaluated;
+ SegmentVector<BackgroundAttributes> 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<style::Layer::Impl>& impl) {
+inline const style::CircleLayer::Impl& impl_cast(const Immutable<style::Layer::Impl>& impl) {
assert(impl->getTypeInfo() == CircleLayer::Impl::staticTypeInfo());
return static_cast<const style::CircleLayer::Impl&>(*impl);
}
@@ -26,11 +26,10 @@ inline const style::CircleLayer::Impl& impl(const Immutable<style::Layer::Impl>&
RenderCircleLayer::RenderCircleLayer(Immutable<style::CircleLayer::Impl> _impl)
: RenderLayer(makeMutable<CircleLayerProperties>(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<style::Layer::Impl>& impl) {
+inline const FillExtrusionLayer::Impl& impl_cast(const Immutable<style::Layer::Impl>& impl) {
assert(impl->getTypeInfo() == FillExtrusionLayer::Impl::staticTypeInfo());
return static_cast<const FillExtrusionLayer::Impl&>(*impl);
}
@@ -32,13 +32,12 @@ inline const FillExtrusionLayer::Impl& impl(const Immutable<style::Layer::Impl>&
RenderFillExtrusionLayer::RenderFillExtrusionLayer(Immutable<style::FillExtrusionLayer::Impl> _impl)
: RenderLayer(makeMutable<FillExtrusionLayerProperties>(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<style::Layer::Impl>& impl) {
+inline const FillLayer::Impl& impl_cast(const Immutable<style::Layer::Impl>& impl) {
assert(impl->getTypeInfo() == FillLayer::Impl::staticTypeInfo());
return static_cast<const FillLayer::Impl&>(*impl);
}
@@ -33,13 +33,12 @@ inline const FillLayer::Impl& impl(const Immutable<style::Layer::Impl>& impl) {
RenderFillLayer::RenderFillLayer(Immutable<style::FillLayer::Impl> _impl)
: RenderLayer(makeMutable<FillLayerProperties>(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 <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/programs/programs.hpp>
-#include <mbgl/programs/heatmap_program.hpp>
#include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/heatmap_layer.hpp>
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
@@ -21,7 +20,7 @@ using namespace style;
namespace {
-inline const HeatmapLayer::Impl& impl(const Immutable<Layer::Impl>& impl) {
+inline const HeatmapLayer::Impl& impl_cast(const Immutable<Layer::Impl>& impl) {
assert(impl->getTypeInfo() == HeatmapLayer::Impl::staticTypeInfo());
return static_cast<const HeatmapLayer::Impl&>(*impl);
}
@@ -30,13 +29,13 @@ inline const HeatmapLayer::Impl& impl(const Immutable<Layer::Impl>& impl) {
RenderHeatmapLayer::RenderHeatmapLayer(Immutable<HeatmapLayer::Impl> _impl)
: RenderLayer(makeMutable<HeatmapLayerProperties>(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 <mbgl/gfx/offscreen_texture.hpp>
+#include <mbgl/gfx/texture.hpp>
+#include <mbgl/programs/heatmap_program.hpp>
#include <mbgl/renderer/render_layer.hpp>
#include <mbgl/style/layers/heatmap_layer_impl.hpp>
#include <mbgl/style/layers/heatmap_layer_properties.hpp>
-#include <mbgl/gfx/texture.hpp>
-#include <mbgl/gfx/offscreen_texture.hpp>
#include <mbgl/util/optional.hpp>
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<gfx::OffscreenTexture> renderTexture;
optional<gfx::Texture> colorRampTexture;
-
- void updateColorRamp();
+ SegmentVector<HeatmapTextureAttributes> 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<style::Layer::Impl>& impl) {
+inline const HillshadeLayer::Impl& impl_cast(const Immutable<style::Layer::Impl>& impl) {
assert(impl->getTypeInfo() == HillshadeLayer::Impl::staticTypeInfo());
return static_cast<const HillshadeLayer::Impl&>(*impl);
}
@@ -29,8 +29,7 @@ inline const HillshadeLayer::Impl& impl(const Immutable<style::Layer::Impl>& imp
RenderHillshadeLayer::RenderHillshadeLayer(Immutable<style::HillshadeLayer::Impl> _impl)
: RenderLayer(makeMutable<HillshadeLayerProperties>(std::move(_impl))),
- unevaluated(impl(baseImpl).paint.untransitioned()) {
-}
+ unevaluated(impl_cast(baseImpl).paint.untransitioned()) {}
RenderHillshadeLayer::~RenderHillshadeLayer() = default;
@@ -48,7 +47,7 @@ const std::array<float, 2> 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<style::Layer::Impl>& impl) {
+inline const LineLayer::Impl& impl_cast(const Immutable<style::Layer::Impl>& impl) {
assert(impl->getTypeInfo() == LineLayer::Impl::staticTypeInfo());
return static_cast<const LineLayer::Impl&>(*impl);
}
@@ -32,14 +32,13 @@ inline const LineLayer::Impl& impl(const Immutable<style::Layer::Impl>& impl) {
RenderLineLayer::RenderLineLayer(Immutable<style::LineLayer::Impl> _impl)
: RenderLayer(makeMutable<LineLayerProperties>(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<style::Layer::Impl>& impl) {
+inline const RasterLayer::Impl& impl_cast(const Immutable<style::Layer::Impl>& impl) {
assert(impl->getTypeInfo() == RasterLayer::Impl::staticTypeInfo());
return static_cast<const RasterLayer::Impl&>(*impl);
}
@@ -25,13 +25,12 @@ inline const RasterLayer::Impl& impl(const Immutable<style::Layer::Impl>& impl)
RenderRasterLayer::RenderRasterLayer(Immutable<style::RasterLayer::Impl> _impl)
: RenderLayer(makeMutable<RasterLayerProperties>(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<style::Layer::Impl>& impl) {
+inline const SymbolLayer::Impl& impl_cast(const Immutable<style::Layer::Impl>& impl) {
assert(impl->getTypeInfo() == SymbolLayer::Impl::staticTypeInfo());
return static_cast<const SymbolLayer::Impl&>(*impl);
}
@@ -299,14 +299,14 @@ inline const SymbolLayer::Impl& impl(const Immutable<style::Layer::Impl>& impl)
RenderSymbolLayer::RenderSymbolLayer(Immutable<style::SymbolLayer::Impl> _impl)
: RenderLayer(makeMutable<SymbolLayerProperties>(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<TextField>());
+ unevaluated = impl_cast(baseImpl).paint.transitioned(parameters, std::move(unevaluated));
+ hasFormatSectionOverrides =
+ SymbolLayerPaintPropertyOverrides::hasOverrides(impl_cast(baseImpl).layout.get<TextField>());
}
void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) {
@@ -314,7 +314,7 @@ void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters)
staticImmutableCast<SymbolLayer::Impl>(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<SymbolSortKey>().isUndefined();
+ const bool sortFeaturesByKey = !impl_cast(baseImpl).layout.get<SymbolSortKey>().isUndefined();
std::multiset<RenderableSegment> renderableSegments;
const auto draw = [&parameters, 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<HeatmapTextureLayoutVertex> 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<BackgroundAttributes> RenderStaticData::tileTriangleSegments() {
+ SegmentVector<BackgroundAttributes> segments;
+ segments.emplace_back(0, 0, 4, 6);
+ return segments;
+}
+
+SegmentVector<DebugAttributes> RenderStaticData::tileBorderSegments() {
+ SegmentVector<DebugAttributes> segments;
+ segments.emplace_back(0, 0, 4, 5);
+ return segments;
+}
+
+SegmentVector<RasterAttributes> RenderStaticData::rasterSegments() {
+ SegmentVector<RasterAttributes> segments;
+ segments.emplace_back(0, 0, 4, 6);
+ return segments;
+}
+
+SegmentVector<HeatmapTextureAttributes> RenderStaticData::heatmapTextureSegments() {
+ SegmentVector<HeatmapTextureAttributes> 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<gfx::IndexBuffer> quadTriangleIndexBuffer;
optional<gfx::IndexBuffer> tileBorderIndexBuffer;
- SegmentVector<BackgroundAttributes> tileTriangleSegments;
- SegmentVector<DebugAttributes> tileBorderSegments;
- SegmentVector<RasterAttributes> rasterSegments;
- SegmentVector<HeatmapTextureAttributes> heatmapTextureSegments;
+ static SegmentVector<BackgroundAttributes> tileTriangleSegments();
+ static SegmentVector<DebugAttributes> tileBorderSegments();
+ static SegmentVector<RasterAttributes> rasterSegments();
+ static SegmentVector<HeatmapTextureAttributes> heatmapTextureSegments();
optional<gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>> depthRenderbuffer;
bool has3D = false;
@@ -42,6 +42,8 @@ public:
Programs programs;
+ const SegmentVector<BackgroundAttributes> 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/sprite/sprite_loader.cpp b/src/mbgl/sprite/sprite_loader.cpp
index 6051de7ef4..60bab2bf6e 100644
--- a/src/mbgl/sprite/sprite_loader.cpp
+++ b/src/mbgl/sprite/sprite_loader.cpp
@@ -58,8 +58,9 @@ void SpriteLoader::load(const std::string& url, FileSource& fileSource) {
} else if (res.noContent) {
loader->json = std::make_shared<std::string>();
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.
+ assert(loader->json != res.data);
loader->json = std::move(res.data);
emitSpriteLoadedIfComplete();
}
@@ -73,7 +74,8 @@ void SpriteLoader::load(const std::string& url, FileSource& fileSource) {
} else if (res.noContent) {
loader->image = std::make_shared<std::string>();
emitSpriteLoadedIfComplete();
- } else if (loader->image != res.data) { // They can be equal - see OnlineFileRequest::completed().
+ } else {
+ assert(loader->image != res.data);
loader->image = std::move(res.data);
emitSpriteLoadedIfComplete();
}
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 <mbgl/util/id.hpp>
-
-#include <atomic>
-
-namespace mbgl {
-namespace util {
-
-uint64_t nextID() {
- static std::atomic<uint64_t> 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 <cstdint>
-
-namespace mbgl {
-namespace util {
-
-uint64_t nextID();
-
-} // namespace util
-} // namespace mbgl
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
+ $<$<STREQUAL:${CMAKE_SYSTEM_NAME},iOS>:-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 $<$<CONFIG:Debug>: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 $<$<CONFIG:Debug>:YES>)
+endif()
+
# Needed for testing private classes
get_target_property(MBGL_CORE_PRIVATE_LIBRARIES mbgl-core LINK_LIBRARIES)
diff --git a/test/fixtures/local_glyphs/ping_fang/expected.png b/test/fixtures/local_glyphs/ping_fang/expected.png
index 2ec62e1bc6..8c891a5232 100644
--- a/test/fixtures/local_glyphs/ping_fang/expected.png
+++ b/test/fixtures/local_glyphs/ping_fang/expected.png
Binary files differ
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 <TargetConditionals.h>
#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/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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN""http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>UnitTestsApp</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.mapbox.UnitTestsApp</string>
+ <key>CFBundleGetInfoString</key>
+ <string>com.mapbox.UnitTestsApp</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>1.0</string>
+ <key>CFBundleLongVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleName</key>
+ <string>com.mapbox.UnitTestsApp</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>MBGL</string>
+ <key>CFBundleVersion</key>
+ <string>7877</string>
+ <key>CSResourcesFileMapped</key>
+ <true/>
+ <key>NSHumanReadableCopyright</key>
+ <string>© 2014–2020 Mapbox</string>
+ <key>LSMinimumSystemVersion</key>
+ <string>${MACOSX_DEPLOYMENT_TARGET}</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen</string>
+ <key>UIMainStoryboardFile</key>
+ <string>Main</string>
+ <key>UIBackgroundModes</key>
+ <array>
+ <string>fetch</string>
+ <string>remote-notification</string>
+ </array>
+ <key>UIRequiredDeviceCapabilities</key>
+ <array>
+ <string>armv7</string>
+ </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ </dict>
+</dict>
+</plist> \ No newline at end of file
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>UnitTestsAppTests</key>
+ <dict>
+ <key>BlueprintName</key>
+ <string>UnitTestsAppTests</string>
+ <key>BundleIdentifiersForCrashReportEmphasis</key>
+ <array>
+ <string>com.mapbox.UnitTestsApp</string>
+ <string>com.mapbox.UnitTestsAppTests</string>
+ </array>
+ <key>CommandLineArguments</key>
+ <array/>
+ <key>DependentProductPaths</key>
+ <array>
+ <string>__TESTROOT__/Debug-iphoneos/UnitTestsApp.app</string>
+ <string>__TESTROOT__/Debug-iphoneos/UnitTestsApp.app/PlugIns/UnitTestsAppTests.xctest</string>
+ </array>
+ <key>EnvironmentVariables</key>
+ <dict>
+ <key>OS_ACTIVITY_DT_MODE</key>
+ <string>YES</string>
+ <key>SQLITE_ENABLE_THREAD_ASSERTIONS</key>
+ <string>1</string>
+ </dict>
+ <key>IsAppHostedTestBundle</key>
+ <true/>
+ <key>ProductModuleName</key>
+ <string>UnitTestsAppTests</string>
+ <key>RunOrder</key>
+ <integer>0</integer>
+ <key>SystemAttachmentLifetime</key>
+ <string>deleteOnSuccess</string>
+ <key>TestBundlePath</key>
+ <string>__TESTHOST__/PlugIns/UnitTestsAppTests.xctest</string>
+ <key>TestHostBundleIdentifier</key>
+ <string>com.mapbox.UnitTestsApp</string>
+ <key>TestHostPath</key>
+ <string>__TESTROOT__/Debug-iphoneos/UnitTestsApp.app</string>
+ <key>TestLanguage</key>
+ <string></string>
+ <key>TestRegion</key>
+ <string></string>
+ <key>TestingEnvironmentVariables</key>
+ <dict>
+ <key>DYLD_FALLBACK_FRAMEWORK_PATH</key>
+ <string></string>
+ <key>DYLD_INSERT_LIBRARIES</key>
+ <string>__PLATFORMS__/iPhoneOS.platform/Developer/usr/lib/libXCTestBundleInject.dylib</string>
+ <key>XCInjectBundleInto</key>
+ <string>unused</string>
+ </dict>
+ <key>ToolchainsSettingValue</key>
+ <array/>
+ <key>UITargetAppCommandLineArguments</key>
+ <array/>
+ <key>UserAttachmentLifetime</key>
+ <string>deleteOnSuccess</string>
+ </dict>
+ <key>__xctestrun_metadata__</key>
+ <dict>
+ <key>FormatVersion</key>
+ <integer>1</integer>
+ </dict>
+</dict>
+</plist>
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>UnitTestsAppTests</key>
+ <dict>
+ <key>BlueprintName</key>
+ <string>UnitTestsAppTests</string>
+ <key>BundleIdentifiersForCrashReportEmphasis</key>
+ <array>
+ <string>com.mapbox.UnitTestsApp</string>
+ <string>com.mapbox.UnitTestsAppTests</string>
+ </array>
+ <key>CommandLineArguments</key>
+ <array/>
+ <key>DependentProductPaths</key>
+ <array>
+ <string>__TESTROOT__/Release-iphoneos/UnitTestsApp.app</string>
+ <string>__TESTROOT__/Release-iphoneos/UnitTestsApp.app/PlugIns/UnitTestsAppTests.xctest</string>
+ </array>
+ <key>EnvironmentVariables</key>
+ <dict>
+ <key>OS_ACTIVITY_DT_MODE</key>
+ <string>YES</string>
+ <key>SQLITE_ENABLE_THREAD_ASSERTIONS</key>
+ <string>1</string>
+ </dict>
+ <key>IsAppHostedTestBundle</key>
+ <true/>
+ <key>ProductModuleName</key>
+ <string>UnitTestsAppTests</string>
+ <key>RunOrder</key>
+ <integer>0</integer>
+ <key>SystemAttachmentLifetime</key>
+ <string>deleteOnSuccess</string>
+ <key>TestBundlePath</key>
+ <string>__TESTHOST__/PlugIns/UnitTestsAppTests.xctest</string>
+ <key>TestHostBundleIdentifier</key>
+ <string>com.mapbox.UnitTestsApp</string>
+ <key>TestHostPath</key>
+ <string>__TESTROOT__/Release-iphoneos/UnitTestsApp.app</string>
+ <key>TestLanguage</key>
+ <string></string>
+ <key>TestRegion</key>
+ <string></string>
+ <key>TestingEnvironmentVariables</key>
+ <dict>
+ <key>DYLD_FALLBACK_FRAMEWORK_PATH</key>
+ <string></string>
+ <key>DYLD_INSERT_LIBRARIES</key>
+ <string>__PLATFORMS__/iPhoneOS.platform/Developer/usr/lib/libXCTestBundleInject.dylib</string>
+ <key>XCInjectBundleInto</key>
+ <string>unused</string>
+ </dict>
+ <key>ToolchainsSettingValue</key>
+ <array/>
+ <key>UITargetAppCommandLineArguments</key>
+ <array/>
+ <key>UserAttachmentLifetime</key>
+ <string>deleteOnSuccess</string>
+ </dict>
+ <key>__xctestrun_metadata__</key>
+ <dict>
+ <key>FormatVersion</key>
+ <integer>1</integer>
+ </dict>
+</dict>
+</plist>
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>application-identifier</key>
+ <string>$TEAM_ID.com.mapbox.UnitTestsApp</string>
+ <key>com.apple.developer.team-identifier</key>
+ <string>$TEAM_ID</string>
+ <key>get-task-allow</key>
+ <true/>
+ <key>keychain-access-groups</key>
+ <array>
+ <string>$TEAM_ID.com.mapbox.UnitTestsApp</string>
+ </array>
+</dict>
+</plist> \ 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>application-identifier</key>
+ <string>$TEAM_ID.com.mapbox.UnitTestsAppTests</string>
+ <key>com.apple.developer.team-identifier</key>
+ <string>$TEAM_ID</string>
+ <key>get-task-allow</key>
+ <true/>
+ <key>keychain-access-groups</key>
+ <array>
+ <string>$TEAM_ID.com.mapbox.UnitTestsAppTests</string>
+ </array>
+</dict>
+</plist> \ 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>application-identifier</key>
+ <string>$TEAM_ID.com.mapbox.UnitTestsAppTests</string>
+ <key>com.apple.developer.team-identifier</key>
+ <string>$TEAM_ID</string>
+ <key>get-task-allow</key>
+ <true/>
+ <key>keychain-access-groups</key>
+ <array>
+ <string>$TEAM_ID.com.mapbox.UnitTestsAppTests</string>
+ </array>
+</dict>
+</plist> \ 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>application-identifier</key>
+ <string>$TEAM_ID.com.mapbox.UnitTestsAppTests</string>
+ <key>com.apple.developer.team-identifier</key>
+ <string>$TEAM_ID</string>
+ <key>get-task-allow</key>
+ <true/>
+ <key>keychain-access-groups</key>
+ <array>
+ <string>$TEAM_ID.com.mapbox.UnitTestsAppTests</string>
+ </array>
+</dict>
+</plist> \ 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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>application-identifier</key>
+ <string>$TEAM_ID.com.mapbox.UnitTestsAppTests</string>
+ <key>com.apple.developer.team-identifier</key>
+ <string>$TEAM_ID</string>
+ <key>get-task-allow</key>
+ <true/>
+ <key>keychain-access-groups</key>
+ <array>
+ <string>$TEAM_ID.com.mapbox.UnitTestsAppTests</string>
+ </array>
+</dict>
+</plist> \ 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 <Foundation/Foundation.h>
+
+__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..d3f6113a05
--- /dev/null
+++ b/test/ios/iosTestRunner.mm
@@ -0,0 +1,82 @@
+#import "iosTestRunner.h"
+
+#include <ios_test_runner.hpp>
+
+#include <string>
+
+@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..c99d8c3f30
--- /dev/null
+++ b/test/ios/ios_test_runner.cpp
@@ -0,0 +1,31 @@
+#include <ios_test_runner.hpp>
+
+#include <mbgl/test.hpp>
+
+#include <mbgl/util/logging.hpp>
+
+#include <unistd.h>
+#include <vector>
+
+#define EXPORT __attribute__((visibility("default")))
+
+EXPORT
+bool TestRunner::startTest(const std::string& basePath) {
+ std::vector<std::string> arguments = {"mbgl-test-runner", "--gtest_output=xml:" + basePath + "/test/results.xml"};
+ std::vector<char*> argv;
+ for (const auto& arg : arguments) {
+ argv.push_back(const_cast<char*>(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<uint32_t>(argv.size()), argv.data());
+ mbgl::Log::Info(mbgl::Event::General, "TestRunner finished with status: '%d'", status);
+
+ return status == 0;
+}
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 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleExecutable</key>
+ <string>UnitTestsAppTests</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.mapbox.UnitTestsAppTests</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>1.0</string>
+ <key>CFBundleName</key>
+ <string>UnitTestsAppTests</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleVersion</key>
+ <string>1</string>
+</dict>
+</plist>
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/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 <mbgl/storage/resource_transform.hpp>
#include <mbgl/test/util.hpp>
#include <mbgl/util/run_loop.hpp>
+#include <mbgl/util/timer.hpp>
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<std::string>("data");
+ response.etag.emplace("snowfall");
+
+ std::unique_ptr<AsyncRequest> 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();
+}
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 a31915498a..7bf5dae267 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<GeometryTileFeature> 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<uint32_t>(time(nullptr)));
std::size_t len = std::rand() % 10000 + 3;
Polygon<double> polygon;
@@ -393,7 +393,7 @@ TEST(TileCover, DISABLED_FuzzPoly) {
TEST(TileCover, DISABLED_FuzzLine) {
while(true)
{
- std::srand (time(nullptr));
+ std::srand(static_cast<uint32_t>(time(nullptr)));
std::size_t len = std::rand() % 10000 + 3;
MultiLineString<double> mls;