Skip to content

Commit 3aef20e

Browse files
committed
[wgpu-hal] Allow importing external WGL contexts as with EGL
1 parent cf0ac22 commit 3aef20e

File tree

5 files changed

+78
-24
lines changed

5 files changed

+78
-24
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ By @wumpf in [#6069](https://github.com/gfx-rs/wgpu/pull/6069), [#6099](https://
8787
#### GLES
8888

8989
- Replace `winapi` code in WGL wrapper to use the `windows` crate. By @MarijnS95 in [#6006](https://github.com/gfx-rs/wgpu/pull/6006)
90+
- Implement `Adapter::new_external()` for WGL (just like EGL) to import an external OpenGL ES context. By @MarijnS95 in [#6152](https://github.com/gfx-rs/wgpu/pull/6152)
9091

9192
#### DX12
9293

Cargo.lock

Lines changed: 12 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wgpu-hal/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ env_logger.workspace = true
207207
glam.workspace = true # for ray-traced-triangle example
208208
winit.workspace = true # for "halmark" example
209209

210-
[target.'cfg(not(any(target_arch = "wasm32", windows, target_os = "ios")))'.dev-dependencies]
211-
glutin-winit = { workspace = true, features = ["egl"] } # for "raw-gles" example
212-
glutin = { workspace = true, features = ["egl"] } # for "raw-gles" example
210+
[target.'cfg(not(any(target_arch = "wasm32", target_os = "ios")))'.dev-dependencies]
211+
glutin-winit = { workspace = true, features = ["egl", "wgl"] } # for "raw-gles" example
212+
glutin = { workspace = true, features = ["egl", "wgl"] } # for "raw-gles" example
213213
rwh_05 = { version = "0.5", package = "raw-window-handle" } # temporary compatibility for glutin-winit in "raw-gles" example
214214
winit = { workspace = true, features = ["rwh_05"] } # for "raw-gles" example

wgpu-hal/examples/raw-gles.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
1111
extern crate wgpu_hal as hal;
1212

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

@@ -254,7 +254,6 @@ fn main() {
254254
}
255255

256256
#[cfg(any(
257-
windows,
258257
all(target_arch = "wasm32", not(target_os = "emscripten")),
259258
target_os = "ios"
260259
))]
@@ -263,7 +262,6 @@ fn main() {
263262
}
264263

265264
#[cfg(not(any(
266-
windows,
267265
all(target_arch = "wasm32", not(target_os = "emscripten")),
268266
target_os = "ios"
269267
)))]

wgpu-hal/src/gles/wgl.rs

Lines changed: 61 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
use glow::HasContext;
2-
use glutin_wgl_sys::wgl_extra::{
3-
Wgl, CONTEXT_CORE_PROFILE_BIT_ARB, CONTEXT_DEBUG_BIT_ARB, CONTEXT_FLAGS_ARB,
4-
CONTEXT_PROFILE_MASK_ARB,
5-
};
6-
use once_cell::sync::Lazy;
7-
use parking_lot::{Mutex, MutexGuard, RwLock};
8-
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
91
use std::{
102
collections::HashSet,
113
ffi::{c_void, CStr, CString},
@@ -19,6 +11,15 @@ use std::{
1911
thread,
2012
time::Duration,
2113
};
14+
15+
use glow::HasContext;
16+
use glutin_wgl_sys::wgl_extra::{
17+
Wgl, CONTEXT_CORE_PROFILE_BIT_ARB, CONTEXT_DEBUG_BIT_ARB, CONTEXT_FLAGS_ARB,
18+
CONTEXT_PROFILE_MASK_ARB,
19+
};
20+
use once_cell::sync::Lazy;
21+
use parking_lot::{Mutex, MutexGuard, RwLock};
22+
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
2223
use wgt::InstanceFlags;
2324
use windows::{
2425
core::{Error, PCSTR},
@@ -48,7 +49,10 @@ impl AdapterContext {
4849
}
4950

5051
pub fn raw_context(&self) -> *mut c_void {
51-
self.inner.lock().context.context.0
52+
match self.inner.lock().context {
53+
Some(ref wgl) => wgl.context.0,
54+
None => ptr::null_mut(),
55+
}
5256
}
5357

5458
/// Obtain a lock to the WGL context and get handle to the [`glow::Context`] that can be used to
@@ -62,7 +66,9 @@ impl AdapterContext {
6266
.try_lock_for(Duration::from_secs(CONTEXT_LOCK_TIMEOUT_SECS))
6367
.expect("Could not lock adapter context. This is most-likely a deadlock.");
6468

65-
inner.context.make_current(inner.device.dc).unwrap();
69+
if let Some(wgl) = &inner.context {
70+
wgl.make_current(inner.device.dc).unwrap()
71+
};
6672

6773
AdapterContextLock { inner }
6874
}
@@ -79,10 +85,11 @@ impl AdapterContext {
7985
.try_lock_for(Duration::from_secs(CONTEXT_LOCK_TIMEOUT_SECS))
8086
.expect("Could not lock adapter context. This is most-likely a deadlock.");
8187

82-
inner
83-
.context
84-
.make_current(device)
85-
.map(|()| AdapterContextLock { inner })
88+
if let Some(wgl) = &inner.context {
89+
wgl.make_current(device)?;
90+
}
91+
92+
Ok(AdapterContextLock { inner })
8693
}
8794
}
8895

@@ -101,7 +108,9 @@ impl<'a> std::ops::Deref for AdapterContextLock<'a> {
101108

102109
impl<'a> Drop for AdapterContextLock<'a> {
103110
fn drop(&mut self) {
104-
self.inner.context.unmake_current().unwrap();
111+
if let Some(wgl) = self.inner.context.take() {
112+
wgl.unmake_current().unwrap()
113+
}
105114
}
106115
}
107116

@@ -136,7 +145,7 @@ unsafe impl Sync for WglContext {}
136145
struct Inner {
137146
gl: glow::Context,
138147
device: InstanceDevice,
139-
context: WglContext,
148+
context: Option<WglContext>,
140149
}
141150

142151
unsafe impl Send for Inner {}
@@ -508,7 +517,7 @@ impl crate::Instance for Instance {
508517
inner: Arc::new(Mutex::new(Inner {
509518
device,
510519
gl,
511-
context,
520+
context: Some(context),
512521
})),
513522
srgb_capable,
514523
})
@@ -550,6 +559,41 @@ impl crate::Instance for Instance {
550559
}
551560
}
552561

562+
impl super::Adapter {
563+
/// Creates a new external adapter using the specified loader function.
564+
///
565+
/// # Safety
566+
///
567+
/// - The underlying OpenGL ES context must be current.
568+
/// - The underlying OpenGL ES context must be current when interfacing with any objects returned by
569+
/// wgpu-hal from this adapter.
570+
pub unsafe fn new_external(
571+
fun: impl FnMut(&str) -> *const c_void,
572+
) -> Option<crate::ExposedAdapter<super::Api>> {
573+
let context = unsafe { glow::Context::from_loader_function(fun) };
574+
unsafe {
575+
Self::expose(AdapterContext {
576+
inner: Arc::new(Mutex::new(Inner {
577+
gl: context,
578+
device: create_instance_device().ok()?,
579+
context: None,
580+
})),
581+
})
582+
}
583+
}
584+
585+
pub fn adapter_context(&self) -> &AdapterContext {
586+
&self.shared.context
587+
}
588+
}
589+
590+
impl super::Device {
591+
/// Returns the underlying WGL context.
592+
pub fn context(&self) -> &AdapterContext {
593+
&self.shared.context
594+
}
595+
}
596+
553597
struct DeviceContextHandle {
554598
device: Gdi::HDC,
555599
window: Foundation::HWND,

0 commit comments

Comments
 (0)