Skip to content

wayland

FreeBodyEngine.graphics.gl44.context.wayland #

Wayland equivalent of create_win32_opengl_context, using EGL instead of WGL (Wayland has no WGL/GLX-style "get a DC and pick a pixel format" API - EGL is the only game in town).

Unlike WGL, EGL doesn't work directly against a wl_surface - Wayland has no native concept of a drawable surface for GL to render into. You have to wrap the wl_surface in a wl_egl_window (from libwayland-egl) first, and that's that which gets handed to eglCreateWindowSurface. This module does that wrapping via ctypes, since PyOpenGL doesn't bind libwayland-egl itself.

Expects window to be a WaylandWindow (see window_wayland.py) - specifically it needs window.native_display (wl_display) and window.native_surface (wl_surface).

Because there's no separate "hdc" object to hang the swap-chain off of like there is on Win32, this stores everything EGL-related it created directly on the window object:

window.egl_display   - EGLDisplay
window.egl_surface   - EGLSurface (the thing you eglSwapBuffers)
window.egl_context   - EGLContext (also returned, for parity with the
                        win32 version returning `hrc`)
window._egl_window   - the underlying wl_egl_window*, needed if you ever
                        call wl_egl_window_resize on a resize event

Dependencies: PyOpenGL (for OpenGL.EGL) and libwayland-egl.so (comes with the wayland client libraries most distros already have installed - it's what any Wayland+EGL app, Qt/GTK/SDL included, links against).

EGL_CONTEXT_MAJOR_VERSION = 12440 module-attribute #

EGL_CONTEXT_MINOR_VERSION = 12539 module-attribute #

EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT = 1 module-attribute #

EGL_CONTEXT_OPENGL_DEBUG = 12720 module-attribute #

EGL_CONTEXT_OPENGL_PROFILE_MASK = 12541 module-attribute #

create_wayland_opengl_context(window, debug) #

Creates a GL 4.4 core-profile context for window via EGL: gets/ initializes the EGL display, binds the OpenGL API, chooses an EGLConfig matching an 8/8/8/8 + 24-depth + 8-stencil framebuffer, wraps window.native_surface in a wl_egl_window (the "native window" EGL needs, since Wayland has no drawable concept of its own), creates the window surface and context, and makes it current. Every EGL handle created is stashed directly on window (there's no single "hdc"-like object to carry them on), and the context is requested as 4.4 core (vs. GL33's equivalent requesting 3.3) - the only real difference from that version of this function. Raises RuntimeError, naming the specific step, on any EGL failure.

destroy_wayland_opengl_context(window) #

Tears down everything create_wayland_opengl_context created on window, in order: releases the current context, destroys the EGL context and surface, destroys the underlying wl_egl_window, then terminates the EGL display connection.

resize_wayland_opengl_surface(window, width, height) #

Call this from the window's resize handler - but note it doesn't resize anything immediately. It just queues the resize; the actual wl_egl_window_resize call happens in swap_wayland_opengl_buffers, right after the next eglSwapBuffers.

This split matters: Wayland-EGL forbids issuing draw calls in between SwapBuffers and wl_egl_window_resize. Calling wl_egl_window_resize straight from an event callback (which can land at any point relative to your frame - mid-draw, pre-swap, whenever) is a known cause of resizes silently doing nothing or the surface hanging/getting stuck at the old size, especially on wlroots-based compositors (Hyprland, Sway) and nVidia's EGLStreams implementation. SDL hit exactly this and fixed it the same way: apply the new size only right after a swap.

swap_wayland_opengl_buffers(window) #

Equivalent of Win32's SwapBuffers(hdc); call this from window.draw().

Plain and unconditional - see the gl33 context module's identical copy of this function for the history of two reverted attempts at skipping it while the surface isn't visible, and why both were removed rather than kept.