Skip to content

Commit 0181b88

Browse files
committed
[wgpu-hal] Implement proper Surface availability semantics in raw-gles example
1 parent a27b027 commit 0181b88

File tree

1 file changed

+95
-49
lines changed

1 file changed

+95
-49
lines changed

wgpu-hal/examples/raw-gles.rs

Lines changed: 95 additions & 49 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,
19+
context::{NotCurrentGlContext, PossiblyCurrentGlContext as _},
2020
display::{GetGlDisplay, GlDisplay},
2121
surface::GlSurface as _,
2222
};
@@ -76,59 +76,16 @@ fn main() {
7676
.with_context_api(glutin::context::ContextApi::Gles(None))
7777
.build(raw_window_handle);
7878

79-
// TODO: Wrap in Option
80-
let mut not_current_gl_context = unsafe {
79+
let mut not_current_gl_context = Some(unsafe {
8180
gl_display
8281
.create_context(&gl_config, &context_attributes)
8382
.expect("failed to create context")
84-
};
85-
86-
// TODO: For Android support this should happen inside Event::Resumed, and the inverse inside ::Suspended.
87-
let window = window.take().unwrap_or_else(|| {
88-
// let window_builder = winit::window::WindowBuilder::new()
89-
// .with_title("WGPU raw GLES example (press Escape to exit)");
90-
// glutin_winit::finalize_window(window_target, window_builder, &gl_config).unwrap()
91-
panic!()
9283
});
9384

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

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

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

0 commit comments

Comments
 (0)