Skip to content

Commit 6af4c60

Browse files
authored
api: add extra EGL and GLX extensions
This patch adds multiple new EGL extensions which are useful for implementing Wayland applications. These have been mostly implemented manually, since gl_generator lacks support for these newer EGL extensions (except for `EGL_KHR_image_base`). The following extensions were added: - EGL_KHR_image_base - EGL_WL_bind_wayland_display - EGL_WL_create_wayland_buffer_from_image This also exposes EGL and GLX raw API calls on EGL and GLX displays.
1 parent e671fbe commit 6af4c60

File tree

12 files changed

+281
-37
lines changed

12 files changed

+281
-37
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
- **Breaking:** updated `raw-window-handle` dependency to `0.6`.
44
- Bump MSRV from `1.65` to `1.70`.
55
- Bump `windows-sys` from `0.48.0` to `0.52.0`.
6+
- Expose `Egl` and `Glx` raw API functions on `Egl` and `Glx` displays.
67

78
# Version 0.31.3
89

glutin/src/api/egl/display.rs

+5
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,11 @@ impl Display {
214214
Device::from_ptr(self.inner.egl, device)
215215
}
216216

217+
/// Get a reference to the initialized EGL API.
218+
pub fn egl(&self) -> &'static Egl {
219+
self.inner.egl
220+
}
221+
217222
/// Terminate the EGL display.
218223
///
219224
/// When the display is managed by glutin with the

glutin/src/api/egl/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ pub(crate) static EGL: Lazy<Option<Egl>> = Lazy::new(|| {
4141
type EglGetProcAddress = unsafe extern "C" fn(*const ffi::c_void) -> *const ffi::c_void;
4242
static EGL_GET_PROC_ADDRESS: OnceCell<libloading_os::Symbol<EglGetProcAddress>> = OnceCell::new();
4343

44-
pub(crate) struct Egl(pub SymWrapper<egl::Egl>);
44+
/// EGL interface.
45+
#[allow(missing_debug_implementations)]
46+
pub struct Egl(SymWrapper<egl::Egl>);
4547

4648
unsafe impl Sync for Egl {}
4749
unsafe impl Send for Egl {}
@@ -68,6 +70,11 @@ impl SymLoading for egl::Egl {
6870
}
6971
};
7072

73+
egl::BindWaylandDisplayWL::load_with(loader);
74+
egl::UnbindWaylandDisplayWL::load_with(loader);
75+
egl::QueryWaylandBufferWL::load_with(loader);
76+
egl::CreateWaylandBufferFromImageWL::load_with(loader);
77+
7178
Self::load_with(loader)
7279
}
7380
}

glutin/src/api/glx/display.rs

+5
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,11 @@ impl Display {
110110
Ok(Self { inner })
111111
}
112112

113+
/// Get a reference to the initialized GLX API.
114+
pub fn glx(&self) -> &'static Glx {
115+
self.inner.glx
116+
}
117+
113118
fn extract_display_features(
114119
extensions: &HashSet<&'static str>,
115120
version: Version,

glutin/src/api/glx/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ static GLX_EXTRA: Lazy<Option<GlxExtra>> = Lazy::new(|| {
5858
Some(GlxExtra::new(glx))
5959
});
6060

61-
pub(crate) struct Glx(pub SymWrapper<glx::Glx>);
61+
/// GLX interface.
62+
#[allow(missing_debug_implementations)]
63+
pub struct Glx(pub SymWrapper<glx::Glx>);
6264

6365
unsafe impl Sync for Glx {}
6466
unsafe impl Send for Glx {}

glutin/src/lib_loading.rs

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub trait SymLoading {
1515
}
1616

1717
#[derive(Clone)]
18+
#[allow(missing_debug_implementations)]
1819
pub struct SymWrapper<T> {
1920
sym: T,
2021
_lib: Arc<Library>,

glutin_egl_sys/build.rs

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ fn main() {
3939
"EGL_KHR_create_context_no_error",
4040
"EGL_KHR_display_reference",
4141
"EGL_KHR_fence_sync",
42+
"EGL_KHR_image_base",
4243
"EGL_KHR_platform_android",
4344
"EGL_KHR_platform_gbm",
4445
"EGL_KHR_platform_wayland",

glutin_egl_sys/src/egl.rs

+252
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
//! Manual implementation of EGL bindings.
2+
//!
3+
//! This is necessary since `gl_generator` is unmaintaned and incapable of
4+
//! generating bindings for some of the newer extensions.
5+
6+
use std::ffi::c_uint;
7+
8+
pub type khronos_utime_nanoseconds_t = super::khronos_utime_nanoseconds_t;
9+
pub type khronos_uint64_t = super::khronos_uint64_t;
10+
pub type khronos_ssize_t = super::khronos_ssize_t;
11+
pub type EGLNativeDisplayType = super::EGLNativeDisplayType;
12+
pub type EGLNativePixmapType = super::EGLNativePixmapType;
13+
pub type EGLNativeWindowType = super::EGLNativeWindowType;
14+
pub type EGLint = super::EGLint;
15+
pub type NativeDisplayType = super::EGLNativeDisplayType;
16+
pub type NativePixmapType = super::EGLNativePixmapType;
17+
pub type NativeWindowType = super::EGLNativeWindowType;
18+
19+
include!(concat!(env!("OUT_DIR"), "/egl_bindings.rs"));
20+
21+
// EGL_EXT_platform_xcb
22+
pub const PLATFORM_XCB_EXT: super::EGLenum = 0x31DC;
23+
pub const PLATFORM_XCB_SCREEN_EXT: super::EGLenum = 0x31DE;
24+
// EGL_EXT_device_query_name
25+
pub const RENDERER_EXT: super::EGLenum = 0x335F;
26+
// EGL_ANGLE_platform_angle - https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/EGL_ANGLE_platform_angle.txt
27+
pub const PLATFORM_ANGLE_ANGLE: super::EGLenum = 0x3202;
28+
pub const PLATFORM_ANGLE_TYPE_ANGLE: super::EGLenum = 0x3203;
29+
pub const PLATFORM_ANGLE_TYPE_VULKAN_ANGLE: super::EGLenum = 0x3450;
30+
pub const PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE: super::EGLenum = 0x3204;
31+
pub const PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE: super::EGLenum = 0x3205;
32+
pub const PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED: super::EGLenum = 0x3451;
33+
pub const PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE: super::EGLenum = 0x348F;
34+
pub const PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: super::EGLenum = 0x3206;
35+
pub const PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: super::EGLenum = 0x320A;
36+
pub const PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: super::EGLenum = 0x345E;
37+
38+
mod wayland_storage {
39+
use super::FnPtr;
40+
use super::__gl_imports::raw;
41+
42+
// EGL_WL_create_wayland_buffer_from_image
43+
pub static mut CREATE_WAYLAND_BUFFER_FROM_IMAGE_WL: FnPtr =
44+
FnPtr { f: super::missing_fn_panic as *const raw::c_void, is_loaded: false };
45+
46+
// EGL_WL_bind_wayland_display
47+
pub static mut BIND_WAYLAND_DISPLAY_WL: FnPtr =
48+
FnPtr { f: super::missing_fn_panic as *const raw::c_void, is_loaded: false };
49+
pub static mut UNBIND_WAYLAND_DISPLAY_WL: FnPtr =
50+
FnPtr { f: super::missing_fn_panic as *const raw::c_void, is_loaded: false };
51+
pub static mut QUERY_WAYLAND_BUFFER_WL: FnPtr =
52+
FnPtr { f: super::missing_fn_panic as *const raw::c_void, is_loaded: false };
53+
}
54+
55+
impl Egl {
56+
#[allow(non_snake_case, unused_variables, dead_code)]
57+
#[inline]
58+
pub unsafe fn CreateWaylandBufferFromImageWL(
59+
&self,
60+
dpy: types::EGLDisplay,
61+
image: types::EGLImageKHR,
62+
) -> *mut std::ffi::c_void {
63+
__gl_imports::mem::transmute::<
64+
_,
65+
extern "system" fn(types::EGLDisplay, types::EGLImageKHR) -> *mut std::ffi::c_void,
66+
>(wayland_storage::CREATE_WAYLAND_BUFFER_FROM_IMAGE_WL.f)(dpy, image)
67+
}
68+
69+
#[allow(non_snake_case, unused_variables, dead_code)]
70+
#[inline]
71+
pub unsafe fn BindWaylandDisplayWL(
72+
&self,
73+
dpy: types::EGLDisplay,
74+
display: *mut __gl_imports::raw::c_void,
75+
) -> types::EGLBoolean {
76+
__gl_imports::mem::transmute::<
77+
_,
78+
extern "system" fn(
79+
types::EGLDisplay,
80+
*mut __gl_imports::raw::c_void,
81+
) -> types::EGLBoolean,
82+
>(wayland_storage::BIND_WAYLAND_DISPLAY_WL.f)(dpy, display)
83+
}
84+
85+
#[allow(non_snake_case, unused_variables, dead_code)]
86+
#[inline]
87+
pub unsafe fn UnbindWaylandDisplayWL(
88+
&self,
89+
dpy: types::EGLDisplay,
90+
display: *mut __gl_imports::raw::c_void,
91+
) -> types::EGLBoolean {
92+
__gl_imports::mem::transmute::<
93+
_,
94+
extern "system" fn(
95+
types::EGLDisplay,
96+
*mut __gl_imports::raw::c_void,
97+
) -> types::EGLBoolean,
98+
>(wayland_storage::UNBIND_WAYLAND_DISPLAY_WL.f)(dpy, display)
99+
}
100+
101+
#[allow(non_snake_case, unused_variables, dead_code)]
102+
#[inline]
103+
pub unsafe fn QueryWaylandBufferWL(
104+
&self,
105+
dpy: types::EGLDisplay,
106+
buffer: *mut __gl_imports::raw::c_void,
107+
attribute: types::EGLint,
108+
value: *mut types::EGLint,
109+
) -> types::EGLBoolean {
110+
__gl_imports::mem::transmute::<
111+
_,
112+
extern "system" fn(
113+
types::EGLDisplay,
114+
*mut __gl_imports::raw::c_void,
115+
types::EGLint,
116+
*mut types::EGLint,
117+
) -> types::EGLBoolean,
118+
>(wayland_storage::QUERY_WAYLAND_BUFFER_WL.f)(dpy, buffer, attribute, value)
119+
}
120+
}
121+
122+
// Extension: EGL_WL_create_wayland_buffer_from_image
123+
//
124+
125+
#[allow(non_snake_case)]
126+
pub mod CreateWaylandBufferFromImageWL {
127+
use super::__gl_imports::raw;
128+
use super::{metaloadfn, wayland_storage, FnPtr};
129+
130+
#[inline]
131+
#[allow(dead_code)]
132+
pub fn is_loaded() -> bool {
133+
unsafe { wayland_storage::CREATE_WAYLAND_BUFFER_FROM_IMAGE_WL.is_loaded }
134+
}
135+
136+
#[allow(dead_code)]
137+
pub fn load_with<F>(mut loadfn: F)
138+
where
139+
F: FnMut(&'static str) -> *const raw::c_void,
140+
{
141+
unsafe {
142+
wayland_storage::CREATE_WAYLAND_BUFFER_FROM_IMAGE_WL =
143+
FnPtr::new(metaloadfn(&mut loadfn, "eglCreateWaylandBufferFromImageWL", &[]))
144+
}
145+
}
146+
}
147+
148+
// Extension: EGL_WL_bind_wayland_display
149+
//
150+
151+
// Accepted as <target> in eglCreateImageKHR.
152+
pub const WAYLAND_BUFFER_WL: c_uint = 0x31D5;
153+
// Accepted in the <attrib_list> parameter of eglCreateImageKHR.
154+
pub const WAYLAND_PLANE_WL: c_uint = 0x31D6;
155+
// Possible values for EGL_TEXTURE_FORMAT.
156+
pub const TEXTURE_Y_U_V_WL: i32 = 0x31D7;
157+
pub const TEXTURE_Y_UV_WL: i32 = 0x31D8;
158+
pub const TEXTURE_Y_XUXV_WL: i32 = 0x31D9;
159+
pub const TEXTURE_EXTERNAL_WL: i32 = 0x31DA;
160+
// Accepted in the <attribute> parameter of eglQueryWaylandBufferWL.
161+
pub const EGL_TEXTURE_FORMAT: i32 = 0x3080;
162+
pub const WAYLAND_Y_INVERTED_WL: i32 = 0x31DB;
163+
164+
#[allow(non_snake_case)]
165+
pub mod BindWaylandDisplayWL {
166+
use super::__gl_imports::raw;
167+
use super::{metaloadfn, wayland_storage, FnPtr};
168+
169+
#[inline]
170+
#[allow(dead_code)]
171+
pub fn is_loaded() -> bool {
172+
unsafe { wayland_storage::BIND_WAYLAND_DISPLAY_WL.is_loaded }
173+
}
174+
175+
#[allow(dead_code)]
176+
pub fn load_with<F>(mut loadfn: F)
177+
where
178+
F: FnMut(&'static str) -> *const raw::c_void,
179+
{
180+
unsafe {
181+
wayland_storage::BIND_WAYLAND_DISPLAY_WL =
182+
FnPtr::new(metaloadfn(&mut loadfn, "eglBindWaylandDisplayWL", &[]))
183+
}
184+
}
185+
}
186+
187+
#[allow(non_snake_case)]
188+
pub mod UnbindWaylandDisplayWL {
189+
use super::__gl_imports::raw;
190+
use super::{metaloadfn, wayland_storage, FnPtr};
191+
192+
#[inline]
193+
#[allow(dead_code)]
194+
pub fn is_loaded() -> bool {
195+
unsafe { wayland_storage::UNBIND_WAYLAND_DISPLAY_WL.is_loaded }
196+
}
197+
198+
#[allow(dead_code)]
199+
pub fn load_with<F>(mut loadfn: F)
200+
where
201+
F: FnMut(&'static str) -> *const raw::c_void,
202+
{
203+
unsafe {
204+
wayland_storage::UNBIND_WAYLAND_DISPLAY_WL =
205+
FnPtr::new(metaloadfn(&mut loadfn, "eglUnbindWaylandDisplayWL", &[]))
206+
}
207+
}
208+
}
209+
210+
#[allow(non_snake_case)]
211+
pub mod QueryWaylandBufferWL {
212+
use super::__gl_imports::raw;
213+
use super::{metaloadfn, wayland_storage, FnPtr};
214+
215+
#[inline]
216+
#[allow(dead_code)]
217+
pub fn is_loaded() -> bool {
218+
unsafe { wayland_storage::QUERY_WAYLAND_BUFFER_WL.is_loaded }
219+
}
220+
221+
#[allow(dead_code)]
222+
pub fn load_with<F>(mut loadfn: F)
223+
where
224+
F: FnMut(&'static str) -> *const raw::c_void,
225+
{
226+
unsafe {
227+
wayland_storage::QUERY_WAYLAND_BUFFER_WL =
228+
FnPtr::new(metaloadfn(&mut loadfn, "eglQueryWaylandBufferWL", &[]))
229+
}
230+
}
231+
}
232+
233+
/// OpenGL function loader.
234+
///
235+
/// This is based on the loader generated by `gl_generator`.
236+
#[inline(never)]
237+
fn metaloadfn(
238+
loadfn: &mut dyn FnMut(&'static str) -> *const __gl_imports::raw::c_void,
239+
symbol: &'static str,
240+
fallbacks: &[&'static str],
241+
) -> *const __gl_imports::raw::c_void {
242+
let mut ptr = loadfn(symbol);
243+
if ptr.is_null() {
244+
for &sym in fallbacks {
245+
ptr = loadfn(sym);
246+
if !ptr.is_null() {
247+
break;
248+
}
249+
}
250+
}
251+
ptr
252+
}

glutin_egl_sys/src/lib.rs

+1-31
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,7 @@
1212
#![allow(clippy::manual_non_exhaustive)]
1313
#![allow(clippy::unnecessary_cast)]
1414

15-
pub mod egl {
16-
pub type khronos_utime_nanoseconds_t = super::khronos_utime_nanoseconds_t;
17-
pub type khronos_uint64_t = super::khronos_uint64_t;
18-
pub type khronos_ssize_t = super::khronos_ssize_t;
19-
pub type EGLNativeDisplayType = super::EGLNativeDisplayType;
20-
pub type EGLNativePixmapType = super::EGLNativePixmapType;
21-
pub type EGLNativeWindowType = super::EGLNativeWindowType;
22-
pub type EGLint = super::EGLint;
23-
pub type NativeDisplayType = super::EGLNativeDisplayType;
24-
pub type NativePixmapType = super::EGLNativePixmapType;
25-
pub type NativeWindowType = super::EGLNativeWindowType;
26-
27-
include!(concat!(env!("OUT_DIR"), "/egl_bindings.rs"));
28-
29-
// TODO should upstream these:
30-
// EGL_EXT_platform_xcb
31-
pub const PLATFORM_XCB_EXT: super::EGLenum = 0x31DC;
32-
pub const PLATFORM_XCB_SCREEN_EXT: super::EGLenum = 0x31DE;
33-
// EGL_EXT_device_query_name
34-
pub const RENDERER_EXT: super::EGLenum = 0x335F;
35-
// EGL_ANGLE_platform_angle - https://chromium.googlesource.com/angle/angle/+/HEAD/extensions/EGL_ANGLE_platform_angle.txt
36-
pub const PLATFORM_ANGLE_ANGLE: super::EGLenum = 0x3202;
37-
pub const PLATFORM_ANGLE_TYPE_ANGLE: super::EGLenum = 0x3203;
38-
pub const PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE: super::EGLenum = 0x3204;
39-
pub const PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE: super::EGLenum = 0x3205;
40-
pub const PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED: super::EGLenum = 0x3451;
41-
pub const PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE: super::EGLenum = 0x348F;
42-
pub const PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: super::EGLenum = 0x3206;
43-
pub const PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE: super::EGLenum = 0x320A;
44-
pub const PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE: super::EGLenum = 0x345E;
45-
}
15+
pub mod egl;
4616

4717
pub use self::egl::types::{EGLContext, EGLDisplay};
4818

glutin_examples/examples/egl_device.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ mod example {
112112
}
113113

114114
let path = Path::new(IMG_PATH);
115-
let file = OpenOptions::new().write(true).create(true).open(path).unwrap();
115+
let file = OpenOptions::new().write(true).truncate(true).open(path).unwrap();
116116

117117
let mut encoder = png::Encoder::new(file, 1280, 720);
118118
encoder.set_depth(png::BitDepth::Eight);

glutin_examples/examples/switch_render_thread.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ use glutin::config::ConfigTemplateBuilder;
88
use glutin::context::{ContextAttributesBuilder, PossiblyCurrentContext};
99
use glutin::display::GetGlDisplay;
1010
use glutin::error::{Error as GlutinError, ErrorKind};
11-
use glutin::prelude::{NotCurrentGlContext, PossiblyCurrentGlContext, *};
12-
use glutin::surface::{GlSurface, Surface, WindowSurface};
11+
use glutin::prelude::*;
12+
use glutin::surface::{Surface, WindowSurface};
1313
use glutin_examples::gl::types::GLfloat;
1414
use glutin_examples::{gl_config_picker, Renderer};
1515
use glutin_winit::{self, DisplayBuilder, GlWindow};

0 commit comments

Comments
 (0)