Skip to content

Commit b8d5ae3

Browse files
committed
[wgpu-hal] Implement proper Surface availability semantics in raw-gles example
1 parent 810696d commit b8d5ae3

File tree

1 file changed

+96
-50
lines changed

1 file changed

+96
-50
lines changed

wgpu-hal/examples/raw-gles.rs

Lines changed: 96 additions & 50 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")))]
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
};
@@ -32,7 +32,7 @@ fn main() {
3232
//
3333
// XXX if you don't care about running on Android or so you can safely remove
3434
// this condition and always pass the window builder.
35-
let todo_wgl_backend = true; // cfg!(wgl_backend)
35+
let todo_wgl_backend = false; // cfg!(wgl_backend)
3636
let window_builder = todo_wgl_backend.then(|| {
3737
winit::window::WindowBuilder::new()
3838
.with_title("WGPU raw GLES example (press Escape to exit)")
@@ -80,59 +80,16 @@ fn main() {
8080
.with_context_api(glutin::context::ContextApi::Gles(None))
8181
.build(raw_window_handle);
8282

83-
// TODO: Wrap in Option
84-
let mut not_current_gl_context = unsafe {
83+
let mut not_current_gl_context = Some(unsafe {
8584
gl_display
8685
.create_context(&gl_config, &context_attributes)
8786
.expect("failed to create context")
88-
};
89-
90-
// TODO: For Android support this should happen inside Event::Resumed, and the inverse inside ::Suspended.
91-
let window = window.take().unwrap_or_else(|| {
92-
// let window_builder = winit::window::WindowBuilder::new()
93-
// .with_title("WGPU raw GLES example (press Escape to exit)");
94-
// glutin_winit::finalize_window(window_target, window_builder, &gl_config).unwrap()
95-
panic!()
9687
});
9788

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

127-
let inner_size = window.inner_size();
128-
129-
fill_screen(&exposed, inner_size.width, inner_size.height);
130-
131-
// TODO: Swap in RedrawRequested
132-
println!("Showing the window");
133-
gl_surface
134-
.swap_buffers(&gl_context)
135-
.expect("Failed to swap buffers");
91+
// Only needs to be loaded once
92+
let mut exposed = None;
13693

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

0 commit comments

Comments
 (0)