mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-21 22:33:49 +00:00
[wgpu-hal] Allow importing external WGL contexts as with EGL (#6152)
This commit is contained in:
parent
4e78829d82
commit
960555a426
@ -118,6 +118,7 @@ By @teoxoy [#6134](https://github.com/gfx-rs/wgpu/pull/6134).
|
||||
|
||||
- Replace `winapi` code in WGL wrapper to use the `windows` crate. By @MarijnS95 in [#6006](https://github.com/gfx-rs/wgpu/pull/6006)
|
||||
- Update `glutin` to `0.31` with `glutin-winit` crate. By @MarijnS95 in [#6150](https://github.com/gfx-rs/wgpu/pull/6150) and [#6176](https://github.com/gfx-rs/wgpu/pull/6176)
|
||||
- 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)
|
||||
|
||||
#### DX12
|
||||
|
||||
|
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -1330,12 +1330,14 @@ dependencies = [
|
||||
"core-foundation",
|
||||
"dispatch",
|
||||
"glutin_egl_sys",
|
||||
"glutin_wgl_sys 0.5.0",
|
||||
"icrate",
|
||||
"libloading",
|
||||
"objc2",
|
||||
"once_cell",
|
||||
"raw-window-handle 0.5.2",
|
||||
"wayland-sys",
|
||||
"windows-sys 0.48.0",
|
||||
"x11-dl",
|
||||
]
|
||||
|
||||
@ -1361,6 +1363,15 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_wgl_sys"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead"
|
||||
dependencies = [
|
||||
"gl_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glutin_wgl_sys"
|
||||
version = "0.6.0"
|
||||
@ -3669,7 +3680,7 @@ dependencies = [
|
||||
"glow",
|
||||
"glutin",
|
||||
"glutin-winit",
|
||||
"glutin_wgl_sys",
|
||||
"glutin_wgl_sys 0.6.0",
|
||||
"gpu-alloc",
|
||||
"gpu-allocator",
|
||||
"gpu-descriptor",
|
||||
|
@ -206,8 +206,8 @@ env_logger.workspace = true
|
||||
glam.workspace = true # for ray-traced-triangle example
|
||||
winit.workspace = true # for "halmark" example
|
||||
|
||||
[target.'cfg(not(any(target_arch = "wasm32", windows, target_os = "ios")))'.dev-dependencies]
|
||||
glutin-winit = { workspace = true, features = ["egl", "wayland", "x11"] } # for "raw-gles" example
|
||||
glutin = { workspace = true, features = ["egl", "wayland", "x11"] } # for "raw-gles" example
|
||||
[target.'cfg(not(any(target_arch = "wasm32", target_os = "ios")))'.dev-dependencies]
|
||||
glutin-winit = { workspace = true, features = ["egl", "wgl", "wayland", "x11"] } # for "raw-gles" example
|
||||
glutin = { workspace = true, features = ["egl", "wgl", "wayland", "x11"] } # for "raw-gles" example
|
||||
rwh_05 = { version = "0.5", package = "raw-window-handle" } # temporary compatibility for glutin-winit in "raw-gles" example
|
||||
winit = { workspace = true, features = ["rwh_05"] } # for "raw-gles" example
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
extern crate wgpu_hal as hal;
|
||||
|
||||
#[cfg(not(any(windows, target_arch = "wasm32", target_os = "ios")))]
|
||||
#[cfg(not(any(target_arch = "wasm32", target_os = "ios")))]
|
||||
fn main() {
|
||||
use std::{ffi::CString, num::NonZeroU32};
|
||||
|
||||
@ -255,7 +255,6 @@ fn main() {
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
windows,
|
||||
all(target_arch = "wasm32", not(target_os = "emscripten")),
|
||||
target_os = "ios"
|
||||
))]
|
||||
@ -264,7 +263,6 @@ fn main() {
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
windows,
|
||||
all(target_arch = "wasm32", not(target_os = "emscripten")),
|
||||
target_os = "ios"
|
||||
)))]
|
||||
|
@ -379,7 +379,7 @@ struct EglContextLock<'a> {
|
||||
display: khronos_egl::Display,
|
||||
}
|
||||
|
||||
/// A guard containing a lock to an [`AdapterContext`]
|
||||
/// A guard containing a lock to an [`AdapterContext`], while the GL context is kept current.
|
||||
pub struct AdapterContextLock<'a> {
|
||||
glow: MutexGuard<'a, ManuallyDrop<glow::Context>>,
|
||||
egl: Option<EglContextLock<'a>>,
|
||||
@ -1082,7 +1082,9 @@ impl crate::Instance for Instance {
|
||||
unsafe { gl.debug_message_callback(super::gl_debug_message_callback) };
|
||||
}
|
||||
|
||||
// Avoid accidental drop when the context is not current.
|
||||
// Wrap in ManuallyDrop to make it easier to "current" the GL context before dropping this
|
||||
// GLOW context, which could also happen if a panic occurs after we uncurrent the context
|
||||
// below but before AdapterContext is constructed.
|
||||
let gl = ManuallyDrop::new(gl);
|
||||
inner.egl.unmake_current();
|
||||
|
||||
|
@ -1,11 +1,3 @@
|
||||
use glow::HasContext;
|
||||
use glutin_wgl_sys::wgl_extra::{
|
||||
Wgl, CONTEXT_CORE_PROFILE_BIT_ARB, CONTEXT_DEBUG_BIT_ARB, CONTEXT_FLAGS_ARB,
|
||||
CONTEXT_PROFILE_MASK_ARB,
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use parking_lot::{Mutex, MutexGuard, RwLock};
|
||||
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
ffi::{c_void, CStr, CString},
|
||||
@ -19,6 +11,15 @@ use std::{
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use glow::HasContext;
|
||||
use glutin_wgl_sys::wgl_extra::{
|
||||
Wgl, CONTEXT_CORE_PROFILE_BIT_ARB, CONTEXT_DEBUG_BIT_ARB, CONTEXT_FLAGS_ARB,
|
||||
CONTEXT_PROFILE_MASK_ARB,
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use parking_lot::{Mutex, MutexGuard, RwLock};
|
||||
use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
|
||||
use wgt::InstanceFlags;
|
||||
use windows::{
|
||||
core::{Error, PCSTR},
|
||||
@ -48,7 +49,10 @@ impl AdapterContext {
|
||||
}
|
||||
|
||||
pub fn raw_context(&self) -> *mut c_void {
|
||||
self.inner.lock().context.context.0
|
||||
match self.inner.lock().context {
|
||||
Some(ref wgl) => wgl.context.0,
|
||||
None => ptr::null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
.try_lock_for(Duration::from_secs(CONTEXT_LOCK_TIMEOUT_SECS))
|
||||
.expect("Could not lock adapter context. This is most-likely a deadlock.");
|
||||
|
||||
inner.context.make_current(inner.device.dc).unwrap();
|
||||
if let Some(wgl) = &inner.context {
|
||||
wgl.make_current(inner.device.dc).unwrap()
|
||||
};
|
||||
|
||||
AdapterContextLock { inner }
|
||||
}
|
||||
@ -79,14 +85,15 @@ impl AdapterContext {
|
||||
.try_lock_for(Duration::from_secs(CONTEXT_LOCK_TIMEOUT_SECS))
|
||||
.expect("Could not lock adapter context. This is most-likely a deadlock.");
|
||||
|
||||
inner
|
||||
.context
|
||||
.make_current(device)
|
||||
.map(|()| AdapterContextLock { inner })
|
||||
if let Some(wgl) = &inner.context {
|
||||
wgl.make_current(device)?;
|
||||
}
|
||||
|
||||
Ok(AdapterContextLock { inner })
|
||||
}
|
||||
}
|
||||
|
||||
/// A guard containing a lock to an [`AdapterContext`]
|
||||
/// A guard containing a lock to an [`AdapterContext`], while the GL context is kept current.
|
||||
pub struct AdapterContextLock<'a> {
|
||||
inner: MutexGuard<'a, Inner>,
|
||||
}
|
||||
@ -101,7 +108,9 @@ impl<'a> std::ops::Deref for AdapterContextLock<'a> {
|
||||
|
||||
impl<'a> Drop for AdapterContextLock<'a> {
|
||||
fn drop(&mut self) {
|
||||
self.inner.context.unmake_current().unwrap();
|
||||
if let Some(wgl) = &self.inner.context {
|
||||
wgl.unmake_current().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,7 +145,7 @@ unsafe impl Sync for WglContext {}
|
||||
struct Inner {
|
||||
gl: ManuallyDrop<glow::Context>,
|
||||
device: InstanceDevice,
|
||||
context: WglContext,
|
||||
context: Option<WglContext>,
|
||||
}
|
||||
|
||||
impl Drop for Inner {
|
||||
@ -150,8 +159,14 @@ impl Drop for Inner {
|
||||
|
||||
// Context must be current when dropped. See safety docs on
|
||||
// `glow::HasContext`.
|
||||
self.context.make_current(self.device.dc).unwrap();
|
||||
let _guard = CurrentGuard(&self.context);
|
||||
//
|
||||
// NOTE: This is only set to `None` by `Adapter::new_external` which
|
||||
// requires the context to be current when anything that may be holding
|
||||
// the `Arc<AdapterShared>` is dropped.
|
||||
let _guard = self.context.as_ref().map(|wgl| {
|
||||
wgl.make_current(self.device.dc).unwrap();
|
||||
CurrentGuard(wgl)
|
||||
});
|
||||
// SAFETY: Field not used after this.
|
||||
unsafe { ManuallyDrop::drop(&mut self.gl) };
|
||||
}
|
||||
@ -510,7 +525,9 @@ impl crate::Instance for Instance {
|
||||
unsafe { gl.debug_message_callback(super::gl_debug_message_callback) };
|
||||
}
|
||||
|
||||
// Avoid accidental drop when the context is not current.
|
||||
// Wrap in ManuallyDrop to make it easier to "current" the GL context before dropping this
|
||||
// GLOW context, which could also happen if a panic occurs after we uncurrent the context
|
||||
// below but before Inner is constructed.
|
||||
let gl = ManuallyDrop::new(gl);
|
||||
context.unmake_current().map_err(|e| {
|
||||
crate::InstanceError::with_source(
|
||||
@ -523,7 +540,7 @@ impl crate::Instance for Instance {
|
||||
inner: Arc::new(Mutex::new(Inner {
|
||||
device,
|
||||
gl,
|
||||
context,
|
||||
context: Some(context),
|
||||
})),
|
||||
srgb_capable,
|
||||
})
|
||||
@ -565,6 +582,43 @@ impl crate::Instance for Instance {
|
||||
}
|
||||
}
|
||||
|
||||
impl super::Adapter {
|
||||
/// Creates a new external adapter using the specified loader function.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The underlying OpenGL ES context must be current.
|
||||
/// - The underlying OpenGL ES context must be current when interfacing with any objects returned by
|
||||
/// wgpu-hal from this adapter.
|
||||
/// - The underlying OpenGL ES context must be current when dropping this adapter and when
|
||||
/// dropping any objects returned from this adapter.
|
||||
pub unsafe fn new_external(
|
||||
fun: impl FnMut(&str) -> *const c_void,
|
||||
) -> Option<crate::ExposedAdapter<super::Api>> {
|
||||
let context = unsafe { glow::Context::from_loader_function(fun) };
|
||||
unsafe {
|
||||
Self::expose(AdapterContext {
|
||||
inner: Arc::new(Mutex::new(Inner {
|
||||
gl: ManuallyDrop::new(context),
|
||||
device: create_instance_device().ok()?,
|
||||
context: None,
|
||||
})),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn adapter_context(&self) -> &AdapterContext {
|
||||
&self.shared.context
|
||||
}
|
||||
}
|
||||
|
||||
impl super::Device {
|
||||
/// Returns the underlying WGL context.
|
||||
pub fn context(&self) -> &AdapterContext {
|
||||
&self.shared.context
|
||||
}
|
||||
}
|
||||
|
||||
struct DeviceContextHandle {
|
||||
device: Gdi::HDC,
|
||||
window: Foundation::HWND,
|
||||
|
Loading…
Reference in New Issue
Block a user