From 3c3bea6a0efdc16ed17a756d1d9f6e662782aaea Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 28 May 2026 17:05:25 +0300 Subject: [PATCH 1/3] Default ios.metal to true and document the renderer in the dev guide Flips the IPhoneBuilder default for the ios.metal build hint from false to true so new iOS builds pick the Metal renderer by default. OpenGL ES is deprecated on iOS and the Metal pipeline (#4799) has been stable on master since the polygon-clip fixes for #3921. Users can still opt out with ios.metal=false. Documents the renderer in the developer guide: a new Metal renderer section in Working-With-iOS.asciidoc explains the default and the opt-out, the existing color-space section is reworded to reflect Metal being the default, and the build-hints reference table in Advanced-Topics-Under-The-Hood.asciidoc gains entries for ios.metal and ios.metal.colorSpace (both were missing). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Advanced-Topics-Under-The-Hood.asciidoc | 7 +++++++ docs/developer-guide/Working-With-iOS.asciidoc | 18 ++++++++++++++++-- .../com/codename1/builders/IPhoneBuilder.java | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) 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()) { From 52e5177b862de4de73a844ab7977877b8824b9a1 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 28 May 2026 20:55:11 +0300 Subject: [PATCH 2/3] Pin ios.metal=false in the GL screenshot job The build-ios job exists to exercise the legacy OpenGL ES 2 path. Now that IPhoneBuilder defaults ios.metal to true, that job would silently start running Metal builds, collapsing both jobs onto the same backend. Inject ios.metal=false into hellocodenameone's codenameone_settings.properties before the build, mirroring the ios.metal=true override the build-ios-metal job already does. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/scripts-ios.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.github/workflows/scripts-ios.yml b/.github/workflows/scripts-ios.yml index a65d969500..2c36363f9a 100644 --- a/.github/workflows/scripts-ios.yml +++ b/.github/workflows/scripts-ios.yml @@ -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 From 7cfe9aff25aae026976e1fbb2c1a69babe5665e7 Mon Sep 17 00:00:00 2001 From: Shai Almog <67850168+shai-almog@users.noreply.github.com> Date: Thu, 28 May 2026 22:10:59 +0300 Subject: [PATCH 3/3] Bump iOS screenshot job/step timeouts to accommodate test-suite drain The Metal screenshot job has been timing out at the 30-min test-step cap on master (~60% pass over the last 5 master runs, killed at the CN1SS:SUITE:FINISHED wait). Bump the per-step cap on both the GL and Metal test runs from 30 to 45, and raise the job-level timeout from 45 to 60 so it still covers the longer test envelope. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/scripts-ios.yml | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/.github/workflows/scripts-ios.yml b/.github/workflows/scripts-ios.yml index 2c36363f9a..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 @@ -223,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() @@ -244,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 @@ -428,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