Skip to content

Commit dc33e03

Browse files
committed
[wgpu-hal] Implement proper Surface availability semantics in raw-gles example
1 parent 94ccab7 commit dc33e03

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
};
@@ -73,59 +73,16 @@ fn main() {
7373
.with_context_api(glutin::context::ContextApi::Gles(None))
7474
.build(raw_window_handle);
7575

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

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");
82+
let mut state = None;
11983

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");
84+
// Only needs to be loaded once
85+
let mut exposed = None;
12986

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

0 commit comments

Comments
 (0)