rust-windowing/glutin

Unable to create surface on old i915 system with EGL on X11

Tobi29 opened this issue · 3 comments

Tobi29 commented

Whilst trying to make some glutin based code work on an old machine with Intel 945GME for graphics, I noticed a couple of issues with the EGL backend of glutin when running on Linux with X11:

  • NativeWindow::raw returns a pointer to the window id, instead of the actual window id. This causes eglCreateWindowSurface to fail with EGL_BAD_NATIVE_WINDOW inside of Display::create_window_surface. (There is more code like that around for XCB and pixmaps, which do the same dodgy cast.)
  • DisplayInner::_native_display is never set to anything but None by both Display::new and Display::with_device. This results in X11GlConfigExt::x11_visual always returning None.

Both of these can be avoided by using GLX instead, which is fine, but technically this should work with EGL as well (and it does with at least the first one fixed).
Not a deal breaker, but they both look like oversights to me and they do not cause any issues on newer systems it seems, making them annoying to troubleshoot.

The old system is running Linux 6.1.8 and Mesa 21.3.9 Amber for reference.

NativeWindow::raw returns a pointer to the window id, instead of the actual window id. This causes eglCreateWindowSurface to fail with EGL_BAD_NATIVE_WINDOW inside of Display::create_window_surface. (There is more code like that around for XCB and pixmaps, which do the same dodgy cast.)

The API accepts a pointer though. Have you tried passing XID and not *XID? For me it was straight segfaulting without a cast (which it should for you as well). Like as you can see we take a pointer to a XID not cast XID to pointer.

DisplayInner::_native_display is never set to anything but None by both Display::new and Display::with_device. This results in X11GlConfigExt::x11_visual always returning None.

Now that's a bug, I'm sure it wasn't like that before, and it got somehow changed...

Tobi29 commented

The API accepts a pointer though. Have you tried passing XID and not *XID? For me it was straight segfaulting without a cast (which it should for you as well). Like as you can see we take a pointer to a XID not cast XID to pointer.

I did a little more digging and this seems to be somewhat weird.

By default glutin uses eglCreatePlatformWindowSurface, which in fact does seem to require a pointer to the window id (it is defined as void *native_window). I can confirm that passing *XID works and XID does not, same as for you.
So this code path seems to be fine.
I had this call forcefully disabled when testing so I did not notice it crashing with XID.

On the old system that is unavailable and it falls back to eglCreateWindowSurface, which seems to require the id being passed as-is (it is defined as EGLNativeWindowType win, with EGLNativeWindowType being Window and in turn XID).
On this one I can confirm passing XID works and *XID does not.
Modified window example (disabled transparency) on old system:

Picked a config with 0 samples
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Error { raw_code: Some(12299), raw_os_message: None, kind: BadNativeWindow }', glutin_examples/src/lib.rs:110:83
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Replacing the win argument for eglCreateWindowSurface from native_window.raw() as _ to *(native_window.raw() as *const egl::EGLNativeWindowType):

Picked a config with 0 samples
Running on Mesa DRI Intel(R) 945GME x86/MMX/SSE2
OpenGL Version OpenGL ES 2.0 Mesa 21.3.9 Amber
Shaders version on OpenGL ES GLSL ES 1.0.16

And the window appears correctly and renders.

Now that's a bug, I'm sure it wasn't like that before, and it got somehow changed...

Based on looking through git blame it seems 1679584 broke that by moving construction into a initialize_display function, which always sets it to None.

Based on looking through git blame it seems 1679584 broke that by moving construction into a initialize_display function, which always sets it to None.

That part I've fixed.

Replacing the win argument for eglCreateWindowSurface from native_window.raw() as _ to *(native_window.raw() as *const egl::EGLNativeWindowType):

That's a good call, I'll reiterate and recheck the native window types. I've assumed that the type from Ext just moved to Khr without changing, but it was wrong to assume something like that. I'll post a fix addressing this issue.