Skip to content

Commit 00f9e6e

Browse files
committed
Misc changes and backporting kenny's damaged buffer changes.
Signed-off-by: Hal Gentz <zegentzy@protonmail.com>
1 parent 703b0db commit 00f9e6e

File tree

16 files changed

+439
-33
lines changed

16 files changed

+439
-33
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,4 @@ In order to build in XCode, you must link both `UIKit.framework` and `OpenGLES.f
6969
Help! I'm receiving `NoAvailablePixelFormat`!
7070

7171
- See: https://github.com/rust-windowing/glutin/issues/952#issuecomment-467228004
72-
72+
- If you are on Windows w/ an AMD gpu and are requesting a non-srgb surface, see: https://github.com/rust-windowing/glutin/issues/1219

glutin/src/api/android.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::api::egl::{
66
use crate::platform::android::EventLoopExtAndroid;
77
use crate::CreationError::{self, OsError};
88
use crate::{
9-
Api, ContextError, GlAttributes, PixelFormat, PixelFormatRequirements,
9+
Api, ContextError, GlAttributes, PixelFormat, PixelFormatRequirements, Rect,
1010
};
1111

1212
use glutin_egl_sys as ffi;
@@ -176,6 +176,17 @@ impl Context {
176176
self.0.egl_context.swap_buffers()
177177
}
178178

179+
#[inline]
180+
pub fn swap_buffers_with_damage(&self, rects: &[Rect]) -> Result<(), ContextError> {
181+
if let Some(ref stopped) = self.0.stopped {
182+
let stopped = stopped.lock();
183+
if *stopped {
184+
return Err(ContextError::ContextLost);
185+
}
186+
}
187+
self.0.egl_context.swap_buffers_with_damage(rects)
188+
}
189+
179190
#[inline]
180191
pub fn get_api(&self) -> Api {
181192
self.0.egl_context.get_api()

glutin/src/api/dlloader.rs

+2-15
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
use libloading::Library;
1111

12-
use std::ffi::CString;
1312
use std::ops::{Deref, DerefMut};
1413
use std::sync::Arc;
1514

@@ -20,9 +19,7 @@ pub struct SymWrapper<T> {
2019
}
2120

2221
pub trait SymTrait {
23-
fn load_with<F>(loadfn: F) -> Self
24-
where
25-
F: FnMut(&'static str) -> *const std::os::raw::c_void;
22+
fn load_with(lib: &Library) -> Self;
2623
}
2724

2825
impl<T: SymTrait> SymWrapper<T> {
@@ -31,17 +28,7 @@ impl<T: SymTrait> SymWrapper<T> {
3128
let lib = Library::new(path);
3229
if lib.is_ok() {
3330
return Ok(SymWrapper {
34-
inner: T::load_with(|sym| unsafe {
35-
lib.as_ref()
36-
.unwrap()
37-
.get(
38-
CString::new(sym.as_bytes())
39-
.unwrap()
40-
.as_bytes_with_nul(),
41-
)
42-
.map(|sym| *sym)
43-
.unwrap_or(std::ptr::null_mut())
44-
}),
31+
inner: T::load_with(lib.as_ref().unwrap()),
4532
_lib: Arc::new(lib.unwrap()),
4633
});
4734
}

glutin/src/api/egl.rs

+113-6
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,77 @@
1313
mod egl {
1414
use super::ffi;
1515
use crate::api::dlloader::{SymTrait, SymWrapper};
16+
use libloading;
17+
use std::sync::{Arc, Mutex};
18+
19+
#[cfg(unix)]
20+
use libloading::os::unix as libloading_os;
21+
#[cfg(windows)]
22+
use libloading::os::windows as libloading_os;
1623

1724
#[derive(Clone)]
1825
pub struct Egl(pub SymWrapper<ffi::egl::Egl>);
1926

2027
/// Because `*const raw::c_void` doesn't implement `Sync`.
2128
unsafe impl Sync for Egl {}
2229

30+
type EglGetProcAddressType = libloading_os::Symbol<
31+
unsafe extern "C" fn(
32+
*const std::os::raw::c_void,
33+
) -> *const std::os::raw::c_void,
34+
>;
35+
36+
lazy_static! {
37+
static ref EGL_GET_PROC_ADDRESS: Arc<Mutex<Option<EglGetProcAddressType>>> =
38+
Arc::new(Mutex::new(None));
39+
}
40+
2341
impl SymTrait for ffi::egl::Egl {
24-
fn load_with<F>(loadfn: F) -> Self
25-
where
26-
F: FnMut(&'static str) -> *const std::os::raw::c_void,
27-
{
28-
Self::load_with(loadfn)
42+
fn load_with(lib: &libloading::Library) -> Self {
43+
let f = move |s: &'static str| -> *const std::os::raw::c_void {
44+
// Check if the symbol is available in the library directly. If
45+
// it is, just return it.
46+
match unsafe {
47+
lib.get(
48+
std::ffi::CString::new(s.as_bytes())
49+
.unwrap()
50+
.as_bytes_with_nul(),
51+
)
52+
} {
53+
Ok(sym) => return *sym,
54+
Err(_) => (),
55+
};
56+
57+
let mut egl_get_proc_address =
58+
(*EGL_GET_PROC_ADDRESS).lock().unwrap();
59+
if egl_get_proc_address.is_none() {
60+
unsafe {
61+
let sym: libloading::Symbol<
62+
unsafe extern "C" fn(
63+
*const std::os::raw::c_void,
64+
)
65+
-> *const std::os::raw::c_void,
66+
> = lib.get(b"eglGetProcAddress").unwrap();
67+
*egl_get_proc_address = Some(sym.into_raw());
68+
}
69+
}
70+
71+
// The symbol was not available in the library, so ask
72+
// eglGetProcAddress for it. Note that eglGetProcAddress was
73+
// only able to look up extension functions prior to EGL 1.5,
74+
// hence this two-part dance.
75+
unsafe {
76+
(egl_get_proc_address.as_ref().unwrap())(
77+
std::ffi::CString::new(s.as_bytes())
78+
.unwrap()
79+
.as_bytes_with_nul()
80+
.as_ptr()
81+
as *const std::os::raw::c_void,
82+
)
83+
}
84+
};
85+
86+
Self::load_with(f)
2987
}
3088
}
3189

@@ -65,7 +123,7 @@ use crate::platform_impl::PlatformAttributes;
65123
use crate::{
66124
Api, ContextBuilderWrapper, ContextError, ContextSupports, CreationError,
67125
GlAttributes, GlRequest, PixelFormat, PixelFormatRequirements,
68-
ReleaseBehavior, Robustness,
126+
ReleaseBehavior, Robustness, Rect,
69127
};
70128

71129
use glutin_egl_sys as ffi;
@@ -943,6 +1001,55 @@ impl WindowSurface {
9431001
Ok(())
9441002
}
9451003
}
1004+
1005+
#[inline]
1006+
pub fn swap_buffers_with_damage(
1007+
&self,
1008+
rects: &[Rect],
1009+
) -> Result<(), ContextError> {
1010+
let egl = EGL.as_ref().unwrap();
1011+
1012+
if !egl.SwapBuffersWithDamageKHR.is_loaded() {
1013+
return Err(ContextError::OsError("buffer damage not suported".to_string()));
1014+
}
1015+
1016+
if *self.surface == ffi::egl::NO_SURFACE {
1017+
return Err(ContextError::ContextLost);
1018+
}
1019+
1020+
let mut ffirects: Vec<ffi::egl::types::EGLint> =
1021+
Vec::with_capacity(rects.len() * 4);
1022+
1023+
for rect in rects {
1024+
ffirects.push(rect.x as ffi::egl::types::EGLint);
1025+
ffirects.push(rect.y as ffi::egl::types::EGLint);
1026+
ffirects.push(rect.width as ffi::egl::types::EGLint);
1027+
ffirects.push(rect.height as ffi::egl::types::EGLint);
1028+
}
1029+
1030+
let ret = unsafe {
1031+
egl.SwapBuffersWithDamageKHR(
1032+
**self.display,
1033+
*self.surface,
1034+
ffirects.as_mut_ptr(),
1035+
rects.len() as ffi::egl::types::EGLint,
1036+
)
1037+
};
1038+
1039+
if ret == ffi::egl::FALSE {
1040+
match unsafe { egl.GetError() } as u32 {
1041+
ffi::egl::CONTEXT_LOST => {
1042+
return Err(ContextError::ContextLost)
1043+
}
1044+
err => panic!(
1045+
"swap_buffers: eglSwapBuffers failed (eglGetError returned 0x{:x})",
1046+
err
1047+
),
1048+
}
1049+
} else {
1050+
Ok(())
1051+
}
1052+
}
9461053
}
9471054

9481055
impl PBuffer {

glutin/src/api/glx.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,16 @@ mod glx {
1919
unsafe impl Sync for Glx {}
2020

2121
impl SymTrait for ffi::glx::Glx {
22-
fn load_with<F>(loadfn: F) -> Self
23-
where
24-
F: FnMut(&'static str) -> *const std::os::raw::c_void,
25-
{
26-
Self::load_with(loadfn)
22+
fn load_with(lib: &libloading::Library) -> Self {
23+
Self::load_with(|sym| unsafe {
24+
lib.get(
25+
std::ffi::CString::new(sym.as_bytes())
26+
.unwrap()
27+
.as_bytes_with_nul(),
28+
)
29+
.map(|sym| *sym)
30+
.unwrap_or(std::ptr::null_mut())
31+
})
2732
}
2833
}
2934

glutin/src/api/ios.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
use crate::platform::ios::{WindowBuilderExtIOS, WindowExtIOS};
6464
use crate::{
6565
Api, ContextError, CreationError, GlAttributes, GlRequest, PixelFormat,
66-
PixelFormatRequirements,
66+
PixelFormatRequirements, Rect,
6767
};
6868

6969
use glutin_gles2_sys as ffi;
@@ -327,6 +327,14 @@ impl Context {
327327
}
328328
}
329329

330+
#[inline]
331+
pub fn swap_buffers_with_damage(
332+
&self,
333+
rects: &[Rect],
334+
) -> Result<(), ContextError> {
335+
Err(ContextError::OsError("buffer damage not suported".to_string()))
336+
}
337+
330338
#[inline]
331339
pub fn get_pixel_format(&self) -> PixelFormat {
332340
let color_format = ColorFormat::for_view(self.view);

glutin/src/lib.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ pub struct ContextBuilderWrapper<T> {
168168
pub robustness: Robustness,
169169

170170
/// Platform specific attributes
171-
pub plat_attr: platform_impl::PlatformAttributes,
171+
pub plat_attr: platform_impl::ContextPlatformAttributes,
172172
}
173173

174174
pub type ContextBuilder<'a> = ContextBuilderWrapper<&'a Context>;
@@ -626,6 +626,8 @@ pub struct SurfaceConfigBuilder {
626626
pub pbuffer_support: Option<bool>,
627627
/// FIXME: missing docs
628628
pub window_surface_support: Option<bool>,
629+
630+
pub plat_attr: platform_impl::SurfacePlatformAttributes,
629631
}
630632

631633
impl Default for SurfaceConfigBuilder {
@@ -770,3 +772,12 @@ impl SurfaceConfigBuilder {
770772
self
771773
}
772774
}
775+
776+
// Rectangles to submit as buffer damage.
777+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
778+
pub struct Rect {
779+
pub x: u32,
780+
pub y: u32,
781+
pub width: u32,
782+
pub height: u32,
783+
}

glutin/src/platform_impl/macos/macos.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
use crate::platform::macos::WindowExtMacOS;
33
use crate::{
44
ContextError, CreationError, GlAttributes, PixelFormat,
5-
PixelFormatRequirements, Robustness,
5+
PixelFormatRequirements, Robustness, Rect
66
};
77

88
use cgl::{
@@ -290,6 +290,14 @@ impl Context {
290290
Ok(())
291291
}
292292

293+
#[inline]
294+
pub fn swap_buffers_with_damage(
295+
&self,
296+
rects: &[Rect],
297+
) -> Result<(), ContextError> {
298+
Err(ContextError::OsError("buffer damage not suported".to_string()))
299+
}
300+
293301
#[inline]
294302
pub fn get_api(&self) -> crate::Api {
295303
crate::Api::OpenGl

glutin/src/platform_impl/unix/unix.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ mod wayland;
1212
// use self::x11::X11Context;
1313
use crate::{
1414
Api, ContextBuilderWrapper, ContextError, ContextSupports, CreationError,
15-
GlAttributes, PixelFormat, PixelFormatRequirements,
15+
GlAttributes, PixelFormat, PixelFormatRequirements, Rect,
1616
};
1717
// pub use self::x11::utils as x11_utils;
1818

@@ -288,6 +288,14 @@ impl WindowSurface {
288288
}
289289
}
290290

291+
#[inline]
292+
pub fn swap_buffers_with_damage(&self, rects: &[Rect]) -> Result<(), ContextError> {
293+
match self {
294+
// WindowSurface::X11(ref surface) => surface.swap_buffers_with_damage(rects),
295+
WindowSurface::Wayland(ref surface) => surface.swap_buffers_with_damage(rects),
296+
}
297+
}
298+
291299
#[inline]
292300
pub unsafe fn make_not_current(&self) -> Result<(), ContextError> {
293301
match self {

glutin/src/platform_impl/unix/wayland.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::api::egl::{self, NativeDisplay};
22
use crate::platform_impl::PlatformAttributes;
33
use crate::{
44
ContextBuilderWrapper, ContextError, ContextSupports, CreationError,
5-
GlAttributes, PixelFormat, PixelFormatRequirements,
5+
GlAttributes, PixelFormat, PixelFormatRequirements, Rect,
66
};
77

88
use crate::platform::unix::{
@@ -84,6 +84,14 @@ impl WindowSurface {
8484
self.surface.swap_buffers()
8585
}
8686

87+
#[inline]
88+
pub fn swap_buffers_with_damage(
89+
&self,
90+
rects: &[Rect],
91+
) -> Result<(), ContextError> {
92+
self.surface.swap_buffers_with_damage(rects)
93+
}
94+
8795
#[inline]
8896
pub fn get_pixel_format(&self) -> PixelFormat {
8997
self.surface.get_pixel_format()

glutin/src/platform_impl/unix/x11.rs

+13
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,19 @@ impl Context {
673673
}
674674
}
675675

676+
#[inline]
677+
pub fn swap_buffers_with_damage(
678+
&self,
679+
rects: &[Rect],
680+
) -> Result<(), ContextError> {
681+
match self.context {
682+
X11Context::Glx(_) => Err(ContextError::OsError(
683+
"buffer damage not suported".to_string(),
684+
)),
685+
X11Context::Egl(ref ctx) => ctx.swap_buffers_with_damage(rects),
686+
}
687+
}
688+
676689
#[inline]
677690
pub fn get_pixel_format(&self) -> PixelFormat {
678691
match self.context {

0 commit comments

Comments
 (0)