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 } ;
9
1
use std:: {
10
2
collections:: HashSet ,
11
3
ffi:: { c_void, CStr , CString } ,
@@ -19,6 +11,15 @@ use std::{
19
11
thread,
20
12
time:: Duration ,
21
13
} ;
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 } ;
22
23
use wgt:: InstanceFlags ;
23
24
use windows:: {
24
25
core:: { Error , PCSTR } ,
@@ -48,7 +49,10 @@ impl AdapterContext {
48
49
}
49
50
50
51
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
+ }
52
56
}
53
57
54
58
/// 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 {
62
66
. try_lock_for ( Duration :: from_secs ( CONTEXT_LOCK_TIMEOUT_SECS ) )
63
67
. expect ( "Could not lock adapter context. This is most-likely a deadlock." ) ;
64
68
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
+ } ;
66
72
67
73
AdapterContextLock { inner }
68
74
}
@@ -79,14 +85,15 @@ impl AdapterContext {
79
85
. try_lock_for ( Duration :: from_secs ( CONTEXT_LOCK_TIMEOUT_SECS ) )
80
86
. expect ( "Could not lock adapter context. This is most-likely a deadlock." ) ;
81
87
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 } )
86
93
}
87
94
}
88
95
89
- /// A guard containing a lock to an [`AdapterContext`]
96
+ /// A guard containing a lock to an [`AdapterContext`], while the GL context is kept current.
90
97
pub struct AdapterContextLock < ' a > {
91
98
inner : MutexGuard < ' a , Inner > ,
92
99
}
@@ -101,7 +108,9 @@ impl<'a> std::ops::Deref for AdapterContextLock<'a> {
101
108
102
109
impl < ' a > Drop for AdapterContextLock < ' a > {
103
110
fn drop ( & mut self ) {
104
- self . inner . context . unmake_current ( ) . unwrap ( ) ;
111
+ if let Some ( wgl) = & self . inner . context {
112
+ wgl. unmake_current ( ) . unwrap ( )
113
+ }
105
114
}
106
115
}
107
116
@@ -136,7 +145,7 @@ unsafe impl Sync for WglContext {}
136
145
struct Inner {
137
146
gl : ManuallyDrop < glow:: Context > ,
138
147
device : InstanceDevice ,
139
- context : WglContext ,
148
+ context : Option < WglContext > ,
140
149
}
141
150
142
151
impl Drop for Inner {
@@ -150,8 +159,14 @@ impl Drop for Inner {
150
159
151
160
// Context must be current when dropped. See safety docs on
152
161
// `glow::HasContext`.
153
- self . context . make_current ( self . device . dc ) . unwrap ( ) ;
154
- let _guard = CurrentGuard ( & self . context ) ;
162
+ //
163
+ // NOTE: This is only set to `None` by `Adapter::new_external` which
164
+ // requires the context to be current when anything that may be holding
165
+ // the `Arc<AdapterShared>` is dropped.
166
+ let _guard = self . context . as_ref ( ) . map ( |wgl| {
167
+ wgl. make_current ( self . device . dc ) . unwrap ( ) ;
168
+ CurrentGuard ( wgl)
169
+ } ) ;
155
170
// SAFETY: Field not used after this.
156
171
unsafe { ManuallyDrop :: drop ( & mut self . gl ) } ;
157
172
}
@@ -510,7 +525,9 @@ impl crate::Instance for Instance {
510
525
unsafe { gl. debug_message_callback ( super :: gl_debug_message_callback) } ;
511
526
}
512
527
513
- // Avoid accidental drop when the context is not current.
528
+ // Wrap in ManuallyDrop to make it easier to "current" the GL context before dropping this
529
+ // GLOW context, which could also happen if a panic occurs after we uncurrent the context
530
+ // below but before Inner is constructed.
514
531
let gl = ManuallyDrop :: new ( gl) ;
515
532
context. unmake_current ( ) . map_err ( |e| {
516
533
crate :: InstanceError :: with_source (
@@ -523,7 +540,7 @@ impl crate::Instance for Instance {
523
540
inner : Arc :: new ( Mutex :: new ( Inner {
524
541
device,
525
542
gl,
526
- context,
543
+ context : Some ( context ) ,
527
544
} ) ) ,
528
545
srgb_capable,
529
546
} )
@@ -565,6 +582,43 @@ impl crate::Instance for Instance {
565
582
}
566
583
}
567
584
585
+ impl super :: Adapter {
586
+ /// Creates a new external adapter using the specified loader function.
587
+ ///
588
+ /// # Safety
589
+ ///
590
+ /// - The underlying OpenGL ES context must be current.
591
+ /// - The underlying OpenGL ES context must be current when interfacing with any objects returned by
592
+ /// wgpu-hal from this adapter.
593
+ /// - The underlying OpenGL ES context must be current when dropping this adapter and when
594
+ /// dropping any objects returned from this adapter.
595
+ pub unsafe fn new_external (
596
+ fun : impl FnMut ( & str ) -> * const c_void ,
597
+ ) -> Option < crate :: ExposedAdapter < super :: Api > > {
598
+ let context = unsafe { glow:: Context :: from_loader_function ( fun) } ;
599
+ unsafe {
600
+ Self :: expose ( AdapterContext {
601
+ inner : Arc :: new ( Mutex :: new ( Inner {
602
+ gl : ManuallyDrop :: new ( context) ,
603
+ device : create_instance_device ( ) . ok ( ) ?,
604
+ context : None ,
605
+ } ) ) ,
606
+ } )
607
+ }
608
+ }
609
+
610
+ pub fn adapter_context ( & self ) -> & AdapterContext {
611
+ & self . shared . context
612
+ }
613
+ }
614
+
615
+ impl super :: Device {
616
+ /// Returns the underlying WGL context.
617
+ pub fn context ( & self ) -> & AdapterContext {
618
+ & self . shared . context
619
+ }
620
+ }
621
+
568
622
struct DeviceContextHandle {
569
623
device : Gdi :: HDC ,
570
624
window : Foundation :: HWND ,
0 commit comments