diff --git a/.github/workflows/scripts-ios.yml b/.github/workflows/scripts-ios.yml index a65d969500..3c8b0b6315 100644 --- a/.github/workflows/scripts-ios.yml +++ b/.github/workflows/scripts-ios.yml @@ -76,7 +76,7 @@ jobs: pull-requests: write issues: write runs-on: macos-15 # pinning macos-15 avoids surprises during the cutover window - timeout-minutes: 45 # only sample app build + UI tests now; iOS port build runs in build-port + timeout-minutes: 60 # only sample app build + UI tests now; bumped from 45 to accommodate the 45-min test-step cap concurrency: # ensure only one mac build runs at once group: mac-ci-${{ github.workflow }}-${{ github.ref_name }} cancel-in-progress: true @@ -182,6 +182,28 @@ jobs: key: ${{ needs.build-port.outputs.cn1_built_cache_key }} fail-on-cache-miss: true + - name: Force GL backend for hellocodenameone + # IPhoneBuilder defaults ios.metal to true. The GL job exists to + # exercise the legacy OpenGL ES 2 path, so pin the hint to false + # explicitly. Mirror of the Metal-enabling step in build-ios-metal. + run: | + set -euo pipefail + SETTINGS=scripts/hellocodenameone/common/codenameone_settings.properties + if grep -q '^codename1\.arg\.ios\.metal=' "$SETTINGS"; then + sed -i '' 's|^codename1.arg.ios.metal=.*|codename1.arg.ios.metal=false|' "$SETTINGS" + else + awk ' + /^codename1\.arg\.ios\.applicationQueriesSchemes=/ { + print + print "codename1.arg.ios.metal=false" + next + } + { print } + ' "$SETTINGS" > "$SETTINGS.tmp" && mv "$SETTINGS.tmp" "$SETTINGS" + fi + echo "--- codenameone_settings.properties (ios.* keys after patch) ---" + grep -n 'codename1\.arg\.ios' "$SETTINGS" || true + - name: Build sample iOS app and compile workspace id: build-ios-app run: ./scripts/build-ios-app.sh -q -DskipTests @@ -201,7 +223,11 @@ jobs: "${{ steps.build-ios-app.outputs.workspace }}" \ "" \ "${{ steps.build-ios-app.outputs.scheme }}" - timeout-minutes: 30 + # Bumped from 30 to 45: the Metal screenshot suite has been + # bumping up against the prior 30-min cap on master (timing out + # at the CN1SS:SUITE:FINISHED wait), and the GL job has the + # same envelope so it stays symmetric. + timeout-minutes: 45 - name: Upload iOS artifacts if: always() @@ -222,7 +248,7 @@ jobs: pull-requests: write issues: write runs-on: macos-15 - timeout-minutes: 45 + timeout-minutes: 60 concurrency: group: mac-ci-${{ github.workflow }}-metal-${{ github.ref_name }} cancel-in-progress: true @@ -406,7 +432,10 @@ jobs: "${{ steps.build-ios-app.outputs.workspace }}" \ "" \ "${{ steps.build-ios-app.outputs.scheme }}" - timeout-minutes: 30 + # See the matching note on the GL job: 30-min cap was being + # hit on master while the simulator was still draining the + # screenshot suite. + timeout-minutes: 45 - name: Publish Metal screenshot summary # Surfaces run-ios-ui-tests.sh's comparison result in the job's diff --git a/docs/developer-guide/Advanced-Topics-Under-The-Hood.asciidoc b/docs/developer-guide/Advanced-Topics-Under-The-Hood.asciidoc index dd97842cd5..53b088bb58 100644 --- a/docs/developer-guide/Advanced-Topics-Under-The-Hood.asciidoc +++ b/docs/developer-guide/Advanced-Topics-Under-The-Hood.asciidoc @@ -442,6 +442,12 @@ Only supported for App Store builds. See https://www.codenameone.com/developer-g |ios.testFlight |Boolean true/false defaults to false and works only for pro accounts. Enables the testflight support in the release binaries for easy beta testing. Notice that the IDE plugin has a "Test Flight" check box you *should* use under the iOS section. +|ios.metal +|Boolean true/false defaults to true. Selects the Metal rendering backend (`CAMetalLayer`) over the legacy OpenGL ES 2 path (`CAEAGLLayer`). Metal is the supported iOS graphics API; OpenGL ES is deprecated. Set to `false` to opt out if you hit a Metal-only rendering regression. See link:#_metal_renderer[Working with iOS / Metal renderer] for details. + +|ios.metal.colorSpace +|Selects the `CAMetalLayer.colorspace` for the Metal renderer. Accepts `sRGB` (default), `displayP3`, `deviceRGB`, `linearSRGB`, `extendedSRGB`, `extendedLinearSRGB`, or `none`. Has no effect when `ios.metal=false`. See link:#_choosing_a_color_space_for_the_metal_renderer[Working with iOS / Choosing a color space] for the full table. + |ios.generateSplashScreens |Boolean true/false defaults to false as of 5.0. Enable legacy generation of splash screen images for use when launching the app. These have been replaced now by the new launch storyboards. @@ -1692,6 +1698,7 @@ ios.locationUsageDescription ios.bundleVersion ios.objC ios.testFlight +ios.metal desktop.width desktop.height desktop.adaptToRetina diff --git a/docs/developer-guide/Working-With-iOS.asciidoc b/docs/developer-guide/Working-With-iOS.asciidoc index 278e74fa0d..0bf69ce357 100644 --- a/docs/developer-guide/Working-With-iOS.asciidoc +++ b/docs/developer-guide/Working-With-iOS.asciidoc @@ -177,10 +177,24 @@ NOTE: This is supported for pro users as part of the crash protection feature. To take advantage of that capability use the build hint `ios.testFlight=true` and then submit the app to the store for beta testing. Make sure to use a release build target. +=== Metal renderer + +// vale-skip: Microsoft.Avoid: "rendering backend" is Apple's term of art for an alternate Metal/OpenGL rendering pipeline, not a back-end server. +iOS builds use the Metal rendering backend by default. The Metal pipeline drives a `CAMetalLayer`, replacing the legacy OpenGL ES 2 path on `CAEAGLLayer`. OpenGL ES is deprecated on iOS and Metal is the supported graphics API going forward, so new projects pick it up automatically. + +To opt out and fall back to the OpenGL ES 2 backend, set the build hint: + +[source] +----- +codename1.arg.ios.metal=false +----- + +If you hit a rendering regression after the default flip, opting out with `ios.metal=false` is a safe escape hatch, but please file an issue with a reproducer so the Metal path can be fixed. + === Choosing a color space for the Metal renderer // vale-skip: Microsoft.Avoid: "rendering backend" is Apple's term of art for an alternate Metal/OpenGL rendering pipeline, not a back-end server. -When the Metal rendering backend is enabled with `ios.metal=true`, the `CAMetalLayer` is configured with the sRGB color space by default. This matches the behavior of the legacy OpenGL ES 2 backend on `CAEAGLLayer`: CG-rasterized images and gradients (which are tagged `DeviceRGB` in their `CGBitmapContext`) end up displayed with the same brightness on both backends. +With the Metal renderer (the default), the `CAMetalLayer` is configured with the sRGB color space. This matches the behavior of the legacy OpenGL ES 2 backend on `CAEAGLLayer`: CG-rasterized images and gradients (which are tagged `DeviceRGB` in their `CGBitmapContext`) end up displayed with the same brightness on both backends. // vale-skip: Microsoft.Adverbs: "strictly device-RGB" is a precise color-pipeline qualifier (excluding sRGB conversion), not a softener. For most apps the default is the right choice. Apps that need a different color profile -- for example, wide-gamut artwork that should be displayed in Display P3, or a strictly device-RGB pipeline that matches a custom rendering toolchain -- can override the choice with the `ios.metal.colorSpace` build hint: @@ -212,7 +226,7 @@ For most apps the default is the right choice. Apps that need a different color |=== // vale-skip: Microsoft.Avoid: "OpenGL ES 2 backend" names the alternate rendering pipeline, not a server. -NOTE: The hint only takes effect when `ios.metal=true`. With the OpenGL ES 2 backend the layer is `CAEAGLLayer` and the color space is fixed by the system. +NOTE: The hint only takes effect on the Metal backend (the default). If you have opted out with `ios.metal=false`, the layer is `CAEAGLLayer` and the color space is fixed by the system. === Accessing insecure URLs diff --git a/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/IPhoneBuilder.java b/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/IPhoneBuilder.java index b47e005299..416d1f0c1f 100644 --- a/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/IPhoneBuilder.java +++ b/maven/codenameone-maven-plugin/src/main/java/com/codename1/builders/IPhoneBuilder.java @@ -277,7 +277,7 @@ public boolean build(File sourceZip, BuildRequest request) throws BuildException detectJailbreak = request.getArg("ios.detectJailbreak", "false").equals("true"); defaultEnvironment.put("LANG", "en_US.UTF-8"); tmpFile = tmpDir = getBuildDirectory(); - useMetal = "true".equals(request.getArg("ios.metal", "false")); + useMetal = "true".equals(request.getArg("ios.metal", "true")); log("Request Args: "); log("-----------------"); for (String arg : request.getArgs()) {