OpenGL broken in classic core20 snap on 22.04

Snaps with classic confinement that use OpenGL seem to be broken on Ubuntu 22.04.

To demonstrate this, I have a very simple snap that installs the weston-simple-egl program:

name: test-gl
base: core20
version: '0.1'
summary: using weston-simple-egl to test OpenGL
description: |
  using weston-simple-egl to test OpenGL

grade: stable
confinement: classic

parts:
  weston:
    plugin: nil
    stage-packages:
      - weston

apps:
  test-gl:
    command: usr/bin/weston-simple-egl

This works fine on Ubuntu 20.04 but crashes on Ubuntu 22.04 with:

libEGL warning: MESA-LOADER: failed to open swrast: /usr/lib/dri/swrast_dri.so: cannot open shared object file: No such file or directory (search paths /usr/lib/x86_64-linux-gnu/dri:\$${ORIGIN}/dri:/usr/lib/dri, suffix _dri)

weston-simple-egl: ../clients/simple-egl.c:167: init_egl: Assertion `ret == EGL_TRUE' failed.
Aborted (core dumped)

You are trying to load the mesa drivers from the host into a core20 based process. That only works by chance. (E.g. when running on 20.04)

One solution is to include the 20.04 mesa stack and point LIBGL_DRIVERS_PATH, LIBVA_DRIVERS_PATH and __EGL_VENDOR_LIBRARY_DIRS to it. There’s an example including this here:

Adding the mesa packages and setting the LIBGL_DRIVERS_PATH does the trick:

name: test-gl
base: core20
version: '0.1'
summary: using weston-simple-egl to test OpenGL
description: |
  using weston-simple-egl to test OpenGL

grade: stable
confinement: classic

parts:
  weston:
    plugin: nil
    stage-packages:
      - weston

  mesa-patchelf:
    plugin: nil
    stage-packages:
    - libgl1-mesa-dri
    stage:
      - -usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/dri

  mesa-no-patchelf:
    plugin: nil
    stage-packages:
      - libgl1-mesa-dri
    build-attributes:
      - no-patchelf
    stage:
      - usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/dri

apps:
  test-gl:
    command: usr/bin/weston-simple-egl
    environment:
      LIBGL_DRIVERS_PATH: $SNAP/usr/lib/${SNAPCRAFT_ARCH_TRIPLET}/dri

Is this documented somewhere? It makes sense that the matching mesa libraries have to be installed within the snap. However, I thought that they are already part of the coreXX snap as otherwise, GUI programs cannot run.

It’s also not clear to me, why the libgl1-mesa-dri has to be added twice with and without no-patchelf.

Can you elaborate on what is happening here and why the libgl1-mesa-dri has to be added multiple times? I also think it would be great if this could become something like an extension so that people do not have to search for and copy&paste this boilerplate code.

In a classic snap snapcraft patches binaries to load dependencies from the snap (and not the host). That works for everything except the contents of the dri directory. So there’s one stanza for that, and one for “everything else”.

No, they get pulled in either directly, or via one of a number of extensions.