Skip to content

Commit 6b5d546

Browse files
committed
[wgpu-hal] Implement proper Surface availability semantics in raw-gles example
1 parent e54f96a commit 6b5d546

File tree

1 file changed

+95
-48
lines changed

1 file changed

+95
-48
lines changed

wgpu-hal/examples/raw-gles.rs

Lines changed: 95 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ extern crate wgpu_hal as hal;
1212

1313
#[cfg(not(any(windows, target_arch = "wasm32", target_os = "ios")))]
1414
fn main() {
15-
use std::ffi::CString;
15+
use std::{ffi::CString, num::NonZeroU32};
1616

1717
use glutin::{
1818
config::GlConfig as _,
19-
context::{NotCurrentGlContext as _, Version},
19+
context::{NotCurrentGlContext as _, PossiblyCurrentGlContext as _},
2020
display::{GetGlDisplay as _, GlDisplay as _},
2121
surface::GlSurface as _,
2222
};
@@ -74,58 +74,16 @@ fn main() {
7474
.with_context_api(glutin::context::ContextApi::Gles(Some(Version::new(3, 0))))
7575
.build(raw_window_handle);
7676

77-
// TODO: Wrap in Option
78-
let mut not_current_gl_context = unsafe {
77+
let mut not_current_gl_context = Some(unsafe {
7978
gl_display
8079
.create_context(&gl_config, &context_attributes)
8180
.expect("failed to create context")
82-
};
83-
84-
// TODO: For Android support this should happen inside Event::Resumed, and the inverse inside ::Suspended.
85-
let window = window.take().unwrap_or_else(|| {
86-
let window_builder = winit::window::WindowBuilder::new()
87-
.with_title("WGPU raw GLES example (press Escape to exit)");
88-
glutin_winit::finalize_window(&event_loop, window_builder, &gl_config).unwrap()
8981
});
9082

91-
let attrs = window.build_surface_attributes(Default::default());
92-
let gl_surface = unsafe {
93-
gl_config
94-
.display()
95-
.create_window_surface(&gl_config, &attrs)
96-
.expect("Cannot create GL WindowSurface")
97-
};
98-
99-
// Make it current.
100-
// let gl_context = not_current_gl_context
101-
// .take()
102-
// .unwrap()
103-
// .make_current(&gl_surface)
104-
// .unwrap();
105-
let gl_context = not_current_gl_context
106-
.make_current(&gl_surface)
107-
.expect("GL context cannot be made current with WindowSurface");
108-
109-
println!("Hooking up to wgpu-hal");
110-
let exposed = unsafe {
111-
<hal::api::Gles as hal::Api>::Adapter::new_external(|name| {
112-
// XXX: On WGL this should only be called after the context was made current
113-
gl_config
114-
.display()
115-
.get_proc_address(&CString::new(name).expect(name))
116-
})
117-
}
118-
.expect("GL adapter can't be initialized");
83+
let mut state = None;
11984

120-
let inner_size = window.inner_size();
121-
122-
fill_screen(&exposed, inner_size.width, inner_size.height);
123-
124-
// TODO: Swap in RedrawRequested
125-
println!("Showing the window");
126-
gl_surface
127-
.swap_buffers(&gl_context)
128-
.expect("Failed to swap buffers");
85+
// Only needs to be loaded once
86+
let mut exposed = None;
12987

13088
event_loop
13189
.run(move |event, window_target| {
@@ -151,6 +109,95 @@ fn main() {
151109
..
152110
},
153111
} => window_target.exit(),
112+
Event::Resumed => {
113+
let window = window.take().unwrap_or_else(|| {
114+
let window_builder = winit::window::WindowBuilder::new()
115+
.with_title("WGPU raw GLES example (press Escape to exit)");
116+
glutin_winit::finalize_window(window_target, window_builder, &gl_config)
117+
.unwrap()
118+
});
119+
120+
let attrs = window.build_surface_attributes(Default::default());
121+
let gl_surface = unsafe {
122+
gl_config
123+
.display()
124+
.create_window_surface(&gl_config, &attrs)
125+
.expect("Cannot create GL WindowSurface")
126+
};
127+
128+
// Make it current.
129+
let gl_context = not_current_gl_context
130+
.take()
131+
.unwrap()
132+
.make_current(&gl_surface)
133+
.expect("GL context cannot be made current with WindowSurface");
134+
135+
// The context needs to be current for the Renderer to set up shaders and
136+
// buffers. It also performs function loading, which needs a current context on
137+
// WGL.
138+
println!("Hooking up to wgpu-hal");
139+
exposed.get_or_insert_with(|| {
140+
unsafe {
141+
<hal::api::Gles as hal::Api>::Adapter::new_external(|name| {
142+
// XXX: On WGL this should only be called after the context was made current
143+
gl_config
144+
.display()
145+
.get_proc_address(&CString::new(name).expect(name))
146+
})
147+
}
148+
.expect("GL adapter can't be initialized")
149+
});
150+
151+
assert!(state.replace((gl_context, gl_surface, window)).is_none());
152+
}
153+
Event::Suspended => {
154+
// This event is only raised on Android, where the backing NativeWindow for a GL
155+
// Surface can appear and disappear at any moment.
156+
println!("Android window removed");
157+
158+
// Destroy the GL Surface and un-current the GL Context before ndk-glue releases
159+
// the window back to the system.
160+
let (gl_context, ..) = state.take().unwrap();
161+
assert!(not_current_gl_context
162+
.replace(gl_context.make_not_current().unwrap())
163+
.is_none());
164+
}
165+
Event::WindowEvent {
166+
window_id: _,
167+
event: WindowEvent::Resized(size),
168+
} => {
169+
if size.width != 0 && size.height != 0 {
170+
// Some platforms like EGL require resizing GL surface to update the size
171+
// Notable platforms here are Wayland and macOS, other don't require it
172+
// and the function is no-op, but it's wise to resize it for portability
173+
// reasons.
174+
if let Some((gl_context, gl_surface, _)) = &state {
175+
gl_surface.resize(
176+
gl_context,
177+
NonZeroU32::new(size.width).unwrap(),
178+
NonZeroU32::new(size.height).unwrap(),
179+
);
180+
// XXX: If there's a state for fill_screen(), this would need to be updated too.
181+
}
182+
}
183+
}
184+
Event::WindowEvent {
185+
window_id: _,
186+
event: WindowEvent::RedrawRequested,
187+
} => {
188+
if let (Some(exposed), Some((gl_context, gl_surface, window))) =
189+
(&exposed, &state)
190+
{
191+
let inner_size = window.inner_size();
192+
193+
fill_screen(exposed, inner_size.width, inner_size.height);
194+
195+
println!("Showing the window");
196+
gl_surface
197+
.swap_buffers(gl_context)
198+
.expect("Failed to swap buffers");
199+
}
200+
}
154201
_ => (),
155202
}
156203
})

0 commit comments

Comments
 (0)