Skip to content

Commit 703b0db

Browse files
committed
Merge remote-tracking branch 'upstream/master' into 0.22maj
Signed-off-by: Hal Gentz <zegentzy@protonmail.com>
2 parents 7a99f57 + 1bd2164 commit 703b0db

File tree

7 files changed

+752
-5
lines changed

7 files changed

+752
-5
lines changed

glutin/src/windowed.rs

+347
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
use super::*;
2+
3+
use std::marker::PhantomData;
4+
use winit::event_loop::EventLoop;
5+
use winit::window::{Window, WindowBuilder};
6+
7+
/// Represents an OpenGL [`Context`] and the [`Window`] with which it is
8+
/// associated.
9+
///
10+
/// Please see [`ContextWrapper<T, Window>`].
11+
///
12+
/// # Example
13+
///
14+
/// ```no_run
15+
/// # fn main() {
16+
/// let mut el = glutin::event_loop::EventLoop::new();
17+
/// let wb = glutin::window::WindowBuilder::new();
18+
/// let windowed_context = glutin::ContextBuilder::new()
19+
/// .build_windowed(wb, &el)
20+
/// .unwrap();
21+
///
22+
/// let windowed_context = unsafe { windowed_context.make_current().unwrap() };
23+
/// # }
24+
/// ```
25+
///
26+
/// [`ContextWrapper<T, Window>`]: struct.ContextWrapper.html
27+
/// [`Window`]: struct.Window.html
28+
/// [`Context`]: struct.Context.html
29+
pub type WindowedContext<T> = ContextWrapper<T, Window>;
30+
31+
/// Represents an OpenGL [`Context`] which has an underlying window that is
32+
/// stored separately.
33+
///
34+
/// This type can only be created via one of three ways:
35+
///
36+
/// * [`platform::unix::RawContextExt`]
37+
/// * [`platform::windows::RawContextExt`]
38+
/// * [`WindowedContext<T>::split`]
39+
///
40+
/// Please see [`ContextWrapper<T, ()>`].
41+
///
42+
/// [`ContextWrapper<T, ()>`]: struct.ContextWrapper.html
43+
/// [`WindowedContext<T>::split`]: type.WindowedContext.html#method.split
44+
/// [`Context`]: struct.Context.html
45+
#[cfg_attr(
46+
target_os = "windows",
47+
doc = "\
48+
[`platform::windows::RawContextExt`]: os/windows/enum.RawHandle.html
49+
"
50+
)]
51+
#[cfg_attr(
52+
not(target_os = "windows",),
53+
doc = "\
54+
[`platform::windows::RawContextExt`]: os/index.html
55+
"
56+
)]
57+
#[cfg_attr(
58+
not(any(
59+
target_os = "linux",
60+
target_os = "dragonfly",
61+
target_os = "freebsd",
62+
target_os = "netbsd",
63+
target_os = "openbsd",
64+
)),
65+
doc = "\
66+
[`platform::unix::RawContextExt`]: os/index.html
67+
"
68+
)]
69+
#[cfg_attr(
70+
any(
71+
target_os = "linux",
72+
target_os = "dragonfly",
73+
target_os = "freebsd",
74+
target_os = "netbsd",
75+
target_os = "openbsd",
76+
),
77+
doc = "\
78+
[`platform::unix::RawContextExt`]: os/unix/enum.RawHandle.html
79+
"
80+
)]
81+
pub type RawContext<T> = ContextWrapper<T, ()>;
82+
83+
/// A context which has an underlying window, which may or may not be stored
84+
/// separately.
85+
///
86+
/// If the window is stored separately, it is a [`RawContext<T>`]. Otherwise,
87+
/// it is a [`WindowedContext<T>`].
88+
///
89+
/// [`WindowedContext<T>`]: type.WindowedContext.html
90+
/// [`RawContext<T>`]: type.RawContext.html
91+
/// [`Context`]: struct.Context.html
92+
#[derive(Debug)]
93+
pub struct ContextWrapper<T: ContextCurrentState, W> {
94+
pub(crate) context: Context<T>,
95+
pub(crate) window: W,
96+
}
97+
98+
impl<T: ContextCurrentState> WindowedContext<T> {
99+
/// Borrow the inner `W`.
100+
pub fn window(&self) -> &Window {
101+
&self.window
102+
}
103+
104+
/// Split the [`Window`] apart from the OpenGL [`Context`]. Should only be
105+
/// used when intending to transfer the [`RawContext<T>`] to another
106+
/// thread.
107+
///
108+
/// Unsaftey:
109+
/// - The OpenGL [`Context`] must be dropped before the [`Window`].
110+
///
111+
/// [`RawContext<T>`]: type.RawContext.html
112+
/// [`Window`]: struct.Window.html
113+
/// [`Context`]: struct.Context.html
114+
pub unsafe fn split(self) -> (RawContext<T>, Window) {
115+
(
116+
RawContext {
117+
context: self.context,
118+
window: (),
119+
},
120+
self.window,
121+
)
122+
}
123+
}
124+
125+
impl<W> ContextWrapper<PossiblyCurrent, W> {
126+
/// Swaps the buffers in case of double or triple buffering.
127+
///
128+
/// You should call this function every time you have finished rendering, or
129+
/// the image may not be displayed on the screen.
130+
///
131+
/// **Warning**: if you enabled vsync, this function will block until the
132+
/// next time the screen is refreshed. However drivers can choose to
133+
/// override your vsync settings, which means that you can't know in
134+
/// advance whether `swap_buffers` will block or not.
135+
pub fn swap_buffers(&self) -> Result<(), ContextError> {
136+
self.context.context.swap_buffers()
137+
}
138+
139+
/// Returns the pixel format of the main framebuffer of the context.
140+
pub fn get_pixel_format(&self) -> PixelFormat {
141+
self.context.context.get_pixel_format()
142+
}
143+
144+
/// Resize the context.
145+
///
146+
/// Some platforms (macOS, Wayland) require being manually updated when
147+
/// their window or surface is resized.
148+
///
149+
/// The easiest way of doing this is to take every [`Resized`] window event
150+
/// that is received with a [`LogicalSize`] and convert it to a
151+
/// [`PhysicalSize`] and pass it into this function.
152+
///
153+
/// [`LogicalSize`]: dpi/struct.LogicalSize.html
154+
/// [`PhysicalSize`]: dpi/struct.PhysicalSize.html
155+
/// [`Resized`]: event/enum.WindowEvent.html#variant.Resized
156+
pub fn resize(&self, size: dpi::PhysicalSize) {
157+
let (width, height) = size.into();
158+
self.context.context.resize(width, height);
159+
}
160+
}
161+
162+
impl<T: ContextCurrentState, W> ContextWrapper<T, W> {
163+
/// Borrow the inner GL [`Context`].
164+
///
165+
/// [`Context`]: struct.Context.html
166+
pub fn context(&self) -> &Context<T> {
167+
&self.context
168+
}
169+
170+
/// Sets this context as the current context. The previously current context
171+
/// (if any) is no longer current.
172+
///
173+
/// A failed call to `make_current` might make this, or no context
174+
/// current. It could also keep the previous context current. What happens
175+
/// varies by platform and error.
176+
///
177+
/// To attempt to recover and get back into a know state, either:
178+
///
179+
/// * attempt to use [`is_current`] to find the new current context; or
180+
/// * call [`make_not_current`] on both the previously
181+
/// current context and this context.
182+
///
183+
/// # An higher level overview.
184+
///
185+
/// In OpenGl, only a single context can be current in a thread at a time.
186+
/// Making a new context current will make the old one not current.
187+
/// Contexts can only be sent to different threads if they are not current.
188+
///
189+
/// If you call `make_current` on some context, you should call
190+
/// [`treat_as_not_current`] as soon as possible on the previously current
191+
/// context.
192+
///
193+
/// If you wish to move a currently current context to a different thread,
194+
/// you should do one of two options:
195+
///
196+
/// * Call `make_current` on another context, then call
197+
/// [`treat_as_not_current`] on this context.
198+
/// * Call [`make_not_current`] on this context.
199+
///
200+
/// If you are aware of what context you intend to make current next, it is
201+
/// preferable for performance reasons to call `make_current` on that
202+
/// context, then [`treat_as_not_current`] on this context.
203+
///
204+
/// If you are not aware of what context you intend to make current next,
205+
/// consider waiting until you do. If you need this context not current
206+
/// immediately (e.g. to transfer it to another thread), then call
207+
/// [`make_not_current`] on this context.
208+
///
209+
/// Please avoid calling [`make_not_current`] on one context only to call
210+
/// `make_current` on another context before and/or after. This hurts
211+
/// performance by requiring glutin to:
212+
///
213+
/// * Check if this context is current; then
214+
/// * If it is, change the current context from this context to none; then
215+
/// * Change the current context from none to the new context.
216+
///
217+
/// Instead prefer the method we mentioned above with `make_current` and
218+
/// [`treat_as_not_current`].
219+
///
220+
/// [`make_not_current`]: struct.ContextWrapper.html#method.make_not_current
221+
/// [`treat_as_not_current`]:
222+
/// struct.ContextWrapper.html#method.treat_as_not_current
223+
/// [`is_current`]: struct.ContextWrapper.html#method.is_current
224+
pub unsafe fn make_current(
225+
self,
226+
) -> Result<ContextWrapper<PossiblyCurrent, W>, (Self, ContextError)> {
227+
let window = self.window;
228+
match self.context.make_current() {
229+
Ok(context) => Ok(ContextWrapper { window, context }),
230+
Err((context, err)) => {
231+
Err((ContextWrapper { window, context }, err))
232+
}
233+
}
234+
}
235+
236+
/// If this context is current, makes this context not current. If this
237+
/// context is not current however, this function does nothing.
238+
///
239+
/// Please see [`make_current`].
240+
///
241+
/// [`make_current`]: struct.ContextWrapper.html#method.make_current
242+
pub unsafe fn make_not_current(
243+
self,
244+
) -> Result<ContextWrapper<NotCurrent, W>, (Self, ContextError)> {
245+
let window = self.window;
246+
match self.context.make_not_current() {
247+
Ok(context) => Ok(ContextWrapper { window, context }),
248+
Err((context, err)) => {
249+
Err((ContextWrapper { window, context }, err))
250+
}
251+
}
252+
}
253+
254+
/// Treats this context as not current, even if it is current. We do no
255+
/// checks to confirm that this is actually case.
256+
///
257+
/// If unsure whether or not this context is current, please use
258+
/// [`make_not_current`] which will do nothing if this context is not
259+
/// current.
260+
///
261+
/// Please see [`make_current`].
262+
///
263+
/// [`make_not_current`]: struct.ContextWrapper.html#method.make_not_current
264+
/// [`make_current`]: struct.ContextWrapper.html#method.make_current
265+
pub unsafe fn treat_as_not_current(self) -> ContextWrapper<NotCurrent, W> {
266+
ContextWrapper {
267+
context: self.context.treat_as_not_current(),
268+
window: self.window,
269+
}
270+
}
271+
272+
/// Treats this context as current, even if it is not current. We do no
273+
/// checks to confirm that this is actually case.
274+
///
275+
/// This function should only be used if you intend to track context
276+
/// currency without the limited aid of glutin, and you wish to store
277+
/// all the [`Context`]s as [`NotCurrent`].
278+
///
279+
/// Please see [`make_current`] for the prefered method of handling context
280+
/// currency.
281+
///
282+
/// [`make_current`]: struct.ContextWrapper.html#method.make_current
283+
/// [`NotCurrent`]: enum.NotCurrent.html
284+
/// [`Context`]: struct.Context.html
285+
pub unsafe fn treat_as_current(self) -> ContextWrapper<PossiblyCurrent, W> {
286+
ContextWrapper {
287+
context: self.context.treat_as_current(),
288+
window: self.window,
289+
}
290+
}
291+
292+
/// Returns true if this context is the current one in this thread.
293+
pub fn is_current(&self) -> bool {
294+
self.context.is_current()
295+
}
296+
297+
/// Returns the OpenGL API being used.
298+
pub fn get_api(&self) -> Api {
299+
self.context.get_api()
300+
}
301+
}
302+
303+
impl<W> ContextWrapper<PossiblyCurrent, W> {
304+
/// Returns the address of an OpenGL function.
305+
pub fn get_proc_address(&self, addr: &str) -> *const () {
306+
self.context.get_proc_address(addr)
307+
}
308+
}
309+
310+
impl<T: ContextCurrentState, W> std::ops::Deref for ContextWrapper<T, W> {
311+
type Target = Context<T>;
312+
fn deref(&self) -> &Self::Target {
313+
&self.context
314+
}
315+
}
316+
317+
impl<'a, T: ContextCurrentState> ContextBuilder<'a, T> {
318+
/// Builds the given window along with the associated GL context, returning
319+
/// the pair as a [`WindowedContext<T>`].
320+
///
321+
/// Errors can occur in two scenarios:
322+
/// - If the window could not be created (via permission denied,
323+
/// incompatible system, out of memory, etc.). This should be very rare.
324+
/// - If the OpenGL [`Context`] could not be created. This generally
325+
/// happens
326+
/// because the underlying platform doesn't support a requested feature.
327+
///
328+
/// [`WindowedContext<T>`]: type.WindowedContext.html
329+
/// [`Context`]: struct.Context.html
330+
pub fn build_windowed<TE>(
331+
self,
332+
wb: WindowBuilder,
333+
el: &EventLoop<TE>,
334+
) -> Result<WindowedContext<NotCurrent>, CreationError> {
335+
let ContextBuilder { pf_reqs, gl_attr } = self;
336+
let gl_attr = gl_attr.map_sharing(|ctx| &ctx.context);
337+
platform_impl::Context::new_windowed(wb, el, &pf_reqs, &gl_attr).map(
338+
|(window, context)| WindowedContext {
339+
window,
340+
context: Context {
341+
context,
342+
phantom: PhantomData,
343+
},
344+
},
345+
)
346+
}
347+
}

glutin_egl_sys/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ build = "build.rs"
1010
edition = "2018"
1111

1212
[build-dependencies]
13-
gl_generator = "0.11"
13+
gl_generator = "0.13"
1414

1515
[target.'cfg(target_os = "windows")'.dependencies.winapi]
1616
version = "0.3"

glutin_examples/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@ image = "0.21"
1818
env_logger = "0.6"
1919

2020
[build-dependencies]
21-
gl_generator = "0.11"
21+
gl_generator = "0.13"

0 commit comments

Comments
 (0)