Skip to content

Add JULIA_GLFW_PLATFORM env var to support headless/EGL init on Linux #253

Open

Description

@mkitti

Problem

On Linux, GLFW.Init() unconditionally defaults to PLATFORM_X11:

# src/glfw3.jl
function Init(; platform::Platform = @static Sys.islinux() ? PLATFORM_X11 : ANY_PLATFORM)
    InitHint(PLATFORM, platform)
    ...

__init__() calls Init() with no arguments, so there is no way to override
the platform from the outside — the PLATFORM_X11 default is baked in at
compile time via @static.

This causes headless rendering to fail on GPU cluster nodes that have no X
server, even when the caller explicitly requests EGL-based offscreen rendering:

$ JULIA_GLMAKIE_BACKEND=egl julia --project=glmakie script.jl
ERROR: InitError: Exception[GLFW.GLFWError(65550, "X11: The DISPLAY environment
variable is missing"), ErrorException("glfwInit failed")]

The JULIA_GLMAKIE_BACKEND=egl hint that GLMakie documents for headless use
is silently ignored because GLFW has already failed to initialise before
GLMakie gets a chance to act.

Context

GLFW 3.4 added GLFW_PLATFORM_NULL (value 0x00060005) for exactly this use
case — offscreen window creation with no display system — and it is already
exposed in GLFW.jl as GLFW.PLATFORM_NULL. The constant is present but
unreachable from normal Julia code because __init__() always overwrites the
hint with PLATFORM_X11.

Proposed fix

Read a JULIA_GLFW_PLATFORM environment variable in __init__() and forward
it to Init():

function __init__()
    platform = let s = get(ENV, "JULIA_GLFW_PLATFORM", "")
        if s in ("null", "NULL", "none", "NONE")
            PLATFORM_NULL
        elseif s in ("wayland", "WAYLAND")
            PLATFORM_WAYLAND
        elseif s in ("x11", "X11")
            PLATFORM_X11
        else
            @static Sys.islinux() ? PLATFORM_X11 : ANY_PLATFORM
        end
    end
    Init(platform = platform)
    ...
end

This is a pure addition; the default behaviour is unchanged.

Workaround

Until this is fixed, headless rendering on Linux requires a virtual X server:

xvfb-run -a julia --project=glmakie script.jl

This satisfies GLFW's X11 requirement but uses Mesa software rendering rather
than hardware-accelerated EGL, and requires xvfb-run to be installed on the
compute node.

Environment

  • Julia 1.12
  • GLFW.jl 3.4.6
  • GLMakie 0.13.10
  • Linux (RHEL 9), NVIDIA L4 GPU, no X server on compute nodes

Finding by Claude Sonnet 4.6 (Anthropic) while
working on headless GLMakie movie generation for a scientific computing pipeline.

Activity

  1. mkitti commented on Jun 11, 2026

    @mkitti
    Author

    Follow-up: Testing the proposed fix — OSMesa requirement

    I prototyped the fix described above (adding JULIA_GLFW_PLATFORM env var to __init__()) in a local dev copy of GLFW.jl and tested it on the same HPC cluster that prompted this issue.

    The good news: the fix works at the Init() level. With JULIA_GLFW_PLATFORM=null, GLFW's InitHint(PLATFORM, PLATFORM_NULL) is correctly applied, and GLFW initializes without attempting X11.

    The additional requirement: PLATFORM_NULL requires OSMesa (off-screen Mesa) to be installed on the system. On my cluster nodes, OSMesa is not available:

    GLFWError (API_UNAVAILABLE): OSMesa: Library not found
    

    This surfaces during GLMakie's precompile workload when it calls CreateWindow() to create the singleton screen — so GLMakie itself fails to precompile.

    Two-layer problem summary:

    1. Layer 1 (this issue): __init__() hardcodes PLATFORM_X11, blocking any alternative.
      → Proposed fix (JULIA_GLFW_PLATFORM env var) solves this layer.
    2. Layer 2: PLATFORM_NULL requires OSMesa; PLATFORM_EGL (implicit in Wayland mode) requires EGL. Neither is guaranteed on HPC systems.

    Practical workaround (until both layers are solved): on clusters without OSMesa/EGL but with Xvfb installed, xvfb-run -a julia ... provides a virtual X11 display and the default PLATFORM_X11 works fine (Mesa llvmpipe handles the rendering). GPU nodes can use xvfb-run -a on top of actual hardware rendering once GLMakie connects via X.

    The fix in this PR is still valuable — on systems where OSMesa is installed (many desktop Linux distros and Docker images), JULIA_GLFW_PLATFORM=null would give true headless rendering without Xvfb. Documenting the OSMesa dependency would help users understand what else they need.

    Tested on RHEL 9 + Julia 1.12 + GLMakie v0.13.11. Prototyped fix available at this dev branch as a local override.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions