Skip to content

Commit

Permalink
[wgpu-hal] Allow importing external WGL contexts as with EGL
Browse files Browse the repository at this point in the history
  • Loading branch information
MarijnS95 committed Aug 27, 2024
1 parent 6b5d546 commit 31e084e
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ By @teoxoy [#6134](https://github.com/gfx-rs/wgpu/pull/6134).
#### GLES

- Replace `winapi` code in WGL wrapper to use the `windows` crate. By @MarijnS95 in [#6006](https://github.com/gfx-rs/wgpu/pull/6006)
- 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

Expand Down
15 changes: 13 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions wgpu-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,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"] } # for "raw-gles" example
glutin = { workspace = true, features = ["egl"] } # for "raw-gles" example
[target.'cfg(not(any(target_arch = "wasm32", target_os = "ios")))'.dev-dependencies]
glutin-winit = { workspace = true, features = ["egl", "wgl"] } # for "raw-gles" example
glutin = { workspace = true, features = ["egl", "wgl"] } # 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
4 changes: 1 addition & 3 deletions wgpu-hal/examples/raw-gles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -255,7 +255,6 @@ fn main() {
}

#[cfg(any(
windows,
all(target_arch = "wasm32", not(target_os = "emscripten")),
target_os = "ios"
))]
Expand All @@ -264,7 +263,6 @@ fn main() {
}

#[cfg(not(any(
windows,
all(target_arch = "wasm32", not(target_os = "emscripten")),
target_os = "ios"
)))]
Expand Down
78 changes: 61 additions & 17 deletions wgpu-hal/src/gles/wgl.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand All @@ -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},
Expand Down Expand Up @@ -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
Expand All @@ -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 }
}
Expand All @@ -79,10 +85,11 @@ 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 })
}
}

Expand All @@ -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.take() {
wgl.unmake_current().unwrap()
}
}
}

Expand Down Expand Up @@ -136,7 +145,7 @@ unsafe impl Sync for WglContext {}
struct Inner {
gl: glow::Context,
device: InstanceDevice,
context: WglContext,
context: Option<WglContext>,
}

unsafe impl Send for Inner {}
Expand Down Expand Up @@ -508,7 +517,7 @@ impl crate::Instance for Instance {
inner: Arc::new(Mutex::new(Inner {
device,
gl,
context,
context: Some(context),
})),
srgb_capable,
})
Expand Down Expand Up @@ -550,6 +559,41 @@ 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.
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: 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,
Expand Down

0 comments on commit 31e084e

Please sign in to comment.