Skip to content

Desktop OpenGL 4.6: fall back to the newest available version (Windows / Linux) - #8580

Merged
danoli3 merged 2 commits into
openframeworks:masterfrom
danoli3:desktop-gl46
Oct 13, 2026
Merged

danoli3 merged 2 commits into
openframeworks:masterfrom
danoli3:desktop-gl46

Conversation

@danoli3

@danoli3 danoli3 commented Oct 11, 2026 •

Copy link
Copy Markdown
Member

Follow-up to #8578 (Android ES 3.1 / 3.2), for desktop OpenGL 4.6 on Windows and Linux.

Requesting 4.6 already works on master: settings.setGLVersion(4, 6) goes straight to GLFW as a core-profile context, ofGLSLVersionFromGL(4, 6) returns 460, and the bundled GLEW has GL_VERSION_4_6. Templates can pass it through OF_GL_VERSION_MAJOR / OF_GL_VERSION_MINOR from #8573.

What was missing is the case where the driver can't create the requested version (4.6 on a 4.5 driver, Mesa llvmpipe in CI, older Intel, macOS's 4.1). glfwCreateWindow fails and the app exits with couldn't create GLFW window.

Change (ofAppGLFWWindow.cpp)

  • If window creation fails for a desktop GL 3.2+ request, retry 4.6 → 4.5 → 4.4 → 4.3 → 4.2 → 4.1 → 4.0 → 3.3 → 3.2 (only versions below the request).
  • On success, log a warning (OpenGL 4.6 is not available, using OpenGL 4.5) and update the window settings. ofGLProgrammableRenderer::setup then gets the context's real version, so built-in shaders use the matching #version (e.g. 450, not 460).
  • A successful fallback logs only the warning. The GLFW error is reported only if no version can be created.
  • Requests the driver can satisfy are unchanged.

Tested so far: macOS (M1 Max, GL 4.1 max), glMatrix test app

Requested Result
4.6 falls back to 4.1, GLSL 410, all checks PASS
4.3 falls back to 4.1, all checks PASS
4.1 / 3.3 / 3.2 unchanged, PASS
2.1 unchanged (fixed function), PASS

Before this change, requesting 4.6 or 4.3 on macOS failed to open a window.

Still to test (draft)

  • Windows: ARM64 (Parallels GL 4.3 driver) falls back 4.6 → 4.3; Mesa llvmpipe 4.6 direct and capped 4.5/4.3/4.0/3.3 fallbacks all PASS (results)
  • Windows, NVIDIA / AMD / Intel driver: 4.6 should be created directly (GLSL 460)
  • Linux, native GPU driver: 4.6 directly
    • Tested on virgl (VM, max 4.0) only: 4.6 falls back to 4.0, PASS. Still needs a 4.6-capable driver.
  • Linux, Mesa llvmpipe (CI): 4.6 falls back to 4.5

@danoli3

danoli3 commented Oct 11, 2026

Copy link
Copy Markdown
Member Author

Linux test results (PR head 4c23df3)

Machine: Ubuntu 26.04 LTS, kernel 7.0.0-30, aarch64 VM (Parallels on Apple M1 Max), Wayland session. OF forces GLFW's X11 backend (ofAppGLFWWindow.cpp:47), so all runs go through XWayland / GLX.

glxinfo -B:

Driver Renderer Max core profile
native (virgl) virgl (Apple M1 Max (Compat)), Mesa 26.0.3 4.0
llvmpipe (LIBGL_ALWAYS_SOFTWARE=1) llvmpipe (LLVM 21.1.8, 128 bits), Mesa 26.0.3 4.5

Test app: requested version from OF_GL_VERSION → setGLVersion; checks (a) OF version ≤ real context version, (b) a shader with #version ofGLSLVersionFromGL() compiles, links and draws the expected colour into an FBO, (c) compute shader writes 256 ints to an SSBO (contexts ≥ 4.3), (d) ofDrawCircle / ofDrawRectangle pixels in an FBO, (e) glGetError() == GL_NO_ERROR.

A. Native driver (virgl, max 4.0)

Requested Context OF GLSL Fallback Compute/SSBO Result
4.6 4.0 4.0 400 yes n/a PASS
4.5 4.0 4.0 400 yes n/a PASS
4.3 4.0 4.0 400 yes n/a PASS
4.1 4.0 4.0 400 yes n/a PASS
3.3 4.0 3.3 330 no n/a PASS
3.2 4.0 3.2 150 no n/a PASS
2.1 4.0 2.1 (ofGLRenderer) 120 no n/a PASS

B. llvmpipe (max 4.5)

Requested Context OF GLSL Fallback Compute/SSBO Result
4.6 4.5 4.5 450 yes PASS PASS
4.5 4.5 4.5 450 no PASS PASS
4.3 4.5 4.3 430 no PASS PASS
4.1 4.5 4.1 410 no n/a PASS
3.3 4.5 3.3 330 no n/a PASS
3.2 4.5 3.2 150 no n/a PASS
2.1 4.5 2.1 (ofGLRenderer) 120 no n/a PASS

C. Forced lower maximum (MESA_GL_VERSION_OVERRIDE / MESA_GLSL_VERSION_OVERRIDE), requesting 4.6

Driver + override Context OF GLSL Fallback Compute/SSBO Result
llvmpipe, 4.3 / 430 4.3 4.3 430 yes PASS PASS
llvmpipe, 3.3 / 330 3.3 3.3 330 yes n/a PASS
virgl, 3.3 / 330 3.3 3.3 330 yes n/a PASS

D. Baseline: master (be82516), same app

Config, requesting 4.6 master this PR
virgl couldn't create GLFW window, segfault (exit 139) 4.0, PASS
llvmpipe couldn't create GLFW window, segfault (exit 139) 4.5, PASS
llvmpipe + override 4.3 couldn't create GLFW window, segfault (exit 139) 4.3, PASS
llvmpipe + override 3.3 couldn't create GLFW window, segfault (exit 139) 3.3, PASS

Master log for each of these:

[ error ] ofAppGLFWWindow: 65543: GLX: Failed to create context: GLXBadFBConfig
[ error ] ofAppGLFWWindow: couldn't create GLFW window

Requesting 4.5 on llvmpipe works on master as well, so the PR doesn't change requests the driver can satisfy.

Log checks

  • Every fallback run: exactly one OpenGL X.Y is not available, using OpenGL A.B warning and one GLFW error line (the first failure). The retries are silent.
  • No shader compile/link errors from OF's built-in shaders in any run.
  • No crashes on exit; all PR runs exited 0.

Not covered

  • No driver that creates 4.6 directly. virgl tops out at 4.0, so "Linux, native GPU driver: 4.6 directly" still needs a run on NVIDIA / radeonsi / iris.
  • E (Wayland vs X11): not applicable here. OF always forces GLFW's X11 platform, and there's no plain X11 session on this VM.
  • Unrelated to this PR: on virgl, the 2.1 (fixed-function) ofSaveScreen capture is blank white, even though its FBO checks pass. The output is byte-for-byte identical on master.

Screenshots to follow.

@danoli3

danoli3 commented Oct 11, 2026

Copy link
Copy Markdown
Member Author

all-contact-sheet
A-native-virgl-request-2 1
A-native-virgl-request-3 2
A-native-virgl-request-3 3
A-native-virgl-request-4 1
A-native-virgl-request-4 3
A-native-virgl-request-4 5
A-native-virgl-request-4 6
B-llvmpipe-request-2 1
B-llvmpipe-request-3 2
B-llvmpipe-request-3 3
B-llvmpipe-request-4 1
B-llvmpipe-request-4 3
B-llvmpipe-request-4 5
B-llvmpipe-request-4 6
C-override-3 3-llvmpipe-request-4 6
C-override-3 3-virgl-request-4 6
C-override-4 3-llvmpipe-request-4 6

@danoli3

danoli3 commented Oct 11, 2026 •

Copy link
Copy Markdown
Member Author

Windows test results: PASS

Environment

  • Windows 11 Pro 10.0.26200, ARM64 (Parallels VM on Apple M1 Max), local console session (not RDP)
  • GPU: Parallels Display Adapter (WDDM) driver 20.18.2702.58673. GL: Parallels using Metal (Apple M1 Max), max 4.3 - Build 27.0.2
  • Software GL: Mesa 26.2.4 llvmpipe (LLVM 23.1.2) from mesa-dist-win (x64 build; run under x64 emulation with GALLIUM_OVERRIDE_CPU_CAPS=sse4.1, because llvmpipe's AVX JIT hits illegal instructions under Prism)
  • Toolchain: MSBuild 18 (VS 2026) with the v143 toolset, Release, ARM64 and x64 builds
  • Branch desktop-gl46 @ 4c23df3 (full matrix) and 5150c31 (key cases rerun); baseline master @ be82516

Each run checks: OF version <= context version, an ofShader with #version ofGLSLVersionFromGL() renders the expected colour into an FBO, compute + SSBO (context >= 4.3), ofDrawCircle/ofDrawRectangle FBO readback, and glGetError() after setup and at frame 30.

A. Native driver: Parallels GL 4.3 (ARM64 exe; the x64 exe gives the same results)

requested context OF GLSL fallback compute/SSBO RESULT
4.6 4.3 4.3 430 yes PASS PASS
4.5 4.3 4.3 430 yes PASS PASS
4.3 4.3 4.3 430 no PASS PASS
4.1 4.1 4.1 410 no n/a PASS
3.3 3.3 3.3 330 no n/a PASS
3.2 3.2 3.2 150 no n/a PASS
2.1 4.3 compat 2.1 (fixed-function) 120 no n/a PASS

B. Mesa llvmpipe (x64 exe). Mesa 26.2.4 llvmpipe exposes 4.6 now (not 4.5), so 4.6 is created directly.

requested context OF GLSL fallback compute/SSBO RESULT
4.6 4.6 4.6 460 no PASS PASS
4.3 4.6 4.3 430 no PASS PASS
3.2 4.6 3.2 150 no n/a PASS
2.1 4.6 compat 2.1 120 no n/a PASS

C. llvmpipe with MESA_GL_VERSION_OVERRIDE / MESA_GLSL_VERSION_OVERRIDE

max requested context OF GLSL fallback compute/SSBO RESULT
4.5 / 450 4.6 4.5 4.5 450 yes PASS PASS
4.3 / 430 4.6 4.3 4.3 430 yes PASS PASS
4.3 / 430 4.4 4.3 4.3 430 yes PASS PASS
4.3 / 430 3.2 4.3 3.2 150 no n/a PASS
4.0 / 400 4.6 4.0 4.0 400 yes n/a PASS
3.3 / 330 4.6 3.3 3.3 330 yes n/a PASS

D. Baseline vs PR

driver requested master this PR
Parallels GL 4.3 (native) 4.6 couldn't create GLFW window, process crashes (0xC0000005) falls back to 4.3, PASS
llvmpipe, max 4.3 4.6 couldn't create GLFW window, process crashes (0xC0000005) falls back to 4.3, PASS
llvmpipe, max 4.3 4.3 PASS PASS
llvmpipe (4.6) 4.6 PASS PASS

Logs. At 4c23df3, each fallback run logged one GLFW error (65543: WGL: Failed to create OpenGL context, the first attempt) followed by one OpenGL X.Y is not available, using OpenGL A.B warning. Since 5150c31, a successful fallback logs only the warning. The GLFW error is reported only if every version fails. I reran native 4.6→4.3, llvmpipe 4.6, llvmpipe capped at 4.3 (4.6→4.3), Parallels 4.3/2.1 and the no-core case on 5150c31, and all match. The built-in shaders had no compile or link errors at any version. No hangs and no leftover processes.

No core context at all (llvmpipe capped at 3.1, request 4.6 or 3.2). The PR logs the GLFW error from the first attempt once, then couldn't create GLFW window, with no retry noise. The process then crashes inside OF with 0xC0000005 even when the app does no GL work. master behaves the same, so this is pre-existing and not caused by this PR, but OF should probably exit cleanly when window creation fails.

Not tested: a real 4.6 vendor driver (NVIDIA/AMD/Intel), RDP, GLon12, msys2, and OF_GAME_MODE (which also goes through createWindow).

@danoli3
danoli3 marked this pull request as ready for review October 11, 2026 03:16
@danoli3

danoli3 commented Oct 12, 2026

Copy link
Copy Markdown
Member Author

Tested on Windows and Linux all successfully

Requesting a GL version the driver can't create (e.g. 4.6 on a driver
that tops out at 4.5, Mesa llvmpipe, or macOS's 4.1) made
glfwCreateWindow fail and the app exit with "couldn't create GLFW
window".

ofAppGLFWWindow now retries 4.6 -> 4.5 -> ... -> 3.2 (only versions below
the request) and logs a warning with the version it used. The window
settings are updated, so ofGLProgrammableRenderer is set up with the
context's real version and shaders get the matching #version (e.g. 450
instead of 460). GLFW errors from the retries are silenced; the first
failure is still logged.

Requests the driver can satisfy are unchanged.
@danoli3
danoli3 merged commit 666b730 into openframeworks:master Oct 13, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant