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.