Prime — A strategic board game (MonoGame/SDL2)

name: prime

description: Prime is a strategic board game inspired by chess and checkers. Two opponents face off on a 64-square board. Pieces are marked with a number, which changes when capturing or promoting. Pawns move one square forward; even pieces move forward and sideways; odd pieces move forward and diagonally; Prime pieces (5+) move in any direction like a queen. Each player starts with 8 pawns, 4 even, 2 odd, and 2 Prime pieces. Capture all opponent pieces to win, or have more Prime pieces if both sides have only Primes left.

snapcraft: PRIVATE

upstream: PRIVATE

upstream-relation: The snap publisher is the sole developer of the upstream project.

supported-category: desktop-apps

reasoning: Prime uses MonoGame, a cross-platform game framework that relies on SDL2 + OpenGL for rendering under the hood. Under strict confinement, even with the opengl, desktop, desktop-legacy, x11 and wayland plugs connected, MonoGame’s OpenGL context creation fails — GL.LoadExtensions() crashes with a NullReferenceException because SDL2 cannot create a valid OpenGL context inside the sandbox. This is a known limitation of MonoGame/SDL2 applications under Snap strict confinement. Classic confinement is required for the game to render and run on Linux.

I understand that strict confinement is generally preferred over classic. I’ve tried the existing interfaces to make the snap work under strict confinement.

Thanks.

This is sadly not a supported category, the list of allowed categories can be found here:

Only snaps that fit such a category will be considered for classic …

This request has been added to the queue for review by the @reviewers team.

Thank you, ogra. I understand “desktop-apps” isn’t in the supported list.

Prime is a MonoGame-based board game that relies on SDL2 + OpenGL for rendering. It doesn’t fit any of the existing supported categories. However, since the documentation states that cases outside the existing categories can be discussed with a senior reviewer and an architect, I’d appreciate it if my request could still be evaluated under that process.

The technical reasons remain: GL.LoadExtensions() crashes with NullReferenceException under strict confinement due to SDL2’s inability to create an OpenGL context inside the sandbox, even with all relevant plugs connected.

Thank you.

Could you please reference any public discussion around this issue? Do you know about any snap that was granted classic confinement in the past for similar reasons?

Additionally, could you please share the apparmor denials you find when running the snap strictly confined using the interfaces you mentioned previously?

Thanks

This sounds like a missing interface or a bug in snapd. I’m afraid classic is not an escape hatch, we need to fix the issues you’ve encountered instead. -1 from me for classic.

Thanks both for the feedback. I ran the tests you asked for, here’s what I found.

I rebuilt the snap with strict confinement and plugged everything in (opengl, desktop, desktop-legacy, x11, wayland, pulseaudio, network, home).

The game crashes every time:

Microsoft.Xna.Framework.Graphics.NoSuitableGraphicsDeviceException: Failed to create graphics device! —> System.NullReferenceException: Object reference not set to an instance of an object. at MonoGame.OpenGL.GL.LoadExtensions() at MonoGame.OpenGL.GraphicsContext..ctor(IWindowInfo info) …Copia All plugs are connected (checked with snap connections prime). And here’s the thing — there are zero AppArmor denials. I checked both dmesg and journalctl, nothing at all. So it’s not a permission issue or a missing interface.

@kyrofa, I get your point about classic not being an escape hatch, and I respect that. But in this case the opengl plug is connected and active, no denials show up, and SDL2 still can’t create an OpenGL context inside the sandbox. It’s not that I haven’t tried — I tested with every available interface and the crash is always the same at GL.LoadExtensions().

@jslarraz, regarding public discussions — I couldn’t find much about MonoGame + Snap specifically. The closest thing is MonoGame issue #7230 but that’s about OpenAL, not OpenGL.

If there’s a way to fix this at the snapd or SDL2 level so classic isn’t needed, I’m all for it. But right now the game just can’t create a graphics device under strict confinement with all interfaces connected.

What would you suggest as a next step?

I couldn’t find much about MonoGame + Snap specifically.

Then, your previous This is a known limitation of MonoGame/SDL2 applications under Snap strict confinement. statement is interesting, at the very least…

Microsoft.Xna.Framework.Graphics.NoSuitableGraphicsDeviceException: Failed to create graphics device! —> System.NullReferenceException: Object reference not set to an instance of an object. at MonoGame.OpenGL.GL.LoadExtensions() at MonoGame.OpenGL.GraphicsContext..ctor(IWindowInfo info) …Copia All plugs are connected (checked with snap connections prime). And here’s the thing — there are zero AppArmor denials. I checked both dmesg and journalctl, nothing at all. So it’s not a permission issue or a missing interface.

I think this likely points to a missing dependency in the snap runtime rather than a permissions issue. The first step would be trying to use some of the relevant extension (likely gnome or gpu), if you are not doing so already. If this does not fix the issue, I think you need to check whether you application is able to find the graphics stack within their runtime.

Thank you both so much for your time and patience with this.

@jslarraz you were absolutely right — it was a missing dependency, not a confinement issue. Following your suggestion, I added the gpu extension to the snapcraft.yaml (which pulls in mesa-core22), plus libsdl2, libopenal1, and libpulse0 as stage-packages, along with the right environment variables for PulseAudio.

The game now runs perfectly under strict confinement — OpenGL, SDL2 audio, everything works. No classic confinement needed after all.

I’m sorry for the noise — my initial “known limitation” claim was wrong and I should have tested more thoroughly before making that request. Your guidance saved me a lot of trouble and I learned a lot about how the graphics stack works in snaps.

@kyrofa you were right to push back on this. Classic wasn’t the answer, and I appreciate you pointing that out. The gpu extension + stage-packages approach was exactly what was needed.

I’ll withdraw the classic confinement request. Thanks again for your help!

2 Likes