3
3
use std:: io:: Error as IoError ;
4
4
use std:: marker:: PhantomData ;
5
5
use std:: num:: NonZeroU32 ;
6
+ use std:: os:: raw:: c_int;
6
7
use std:: { fmt, mem} ;
7
8
9
+ use glutin_wgl_sys:: wgl:: types:: GLenum ;
10
+ use glutin_wgl_sys:: wgl_extra:: types:: HPBUFFEREXT ;
11
+ use glutin_wgl_sys:: wgl_extra:: { self } ;
8
12
use raw_window_handle:: RawWindowHandle ;
9
13
use windows_sys:: Win32 :: Foundation :: { HWND , RECT } ;
10
14
use windows_sys:: Win32 :: Graphics :: Gdi :: HDC ;
@@ -36,10 +40,50 @@ impl Display {
36
40
37
41
pub ( crate ) unsafe fn create_pbuffer_surface (
38
42
& self ,
39
- _config : & Config ,
40
- _surface_attributes : & SurfaceAttributes < PbufferSurface > ,
43
+ config : & Config ,
44
+ surface_attributes : & SurfaceAttributes < PbufferSurface > ,
41
45
) -> Result < Surface < PbufferSurface > > {
42
- Err ( ErrorKind :: NotSupported ( "pbuffers are not implemented with WGL" ) . into ( ) )
46
+ let extra = self
47
+ . inner
48
+ . wgl_extra
49
+ . filter ( |_| self . inner . client_extensions . contains ( "WGL_ARB_pbuffer" ) )
50
+ . ok_or ( ErrorKind :: NotSupported ( "pbuffer extensions are not supported" ) ) ?;
51
+
52
+ let hdc = config. inner . hdc ;
53
+ let width = surface_attributes. width . unwrap ( ) . get ( ) as c_int ;
54
+ let height = surface_attributes. height . unwrap ( ) . get ( ) as c_int ;
55
+ let mut attrs = [ 0 ; 3 ] ;
56
+ if surface_attributes. largest_pbuffer {
57
+ attrs[ 0 ] = wgl_extra:: PBUFFER_LARGEST_ARB as c_int ;
58
+ attrs[ 1 ] = 1 ;
59
+ }
60
+
61
+ let hbuf = unsafe {
62
+ extra. CreatePbufferARB (
63
+ hdc as _ ,
64
+ config. inner . pixel_format_index ,
65
+ width,
66
+ height,
67
+ attrs. as_ptr ( ) ,
68
+ )
69
+ } ;
70
+ if hbuf. is_null ( ) {
71
+ return Err ( IoError :: last_os_error ( ) . into ( ) ) ;
72
+ }
73
+
74
+ let hdc = unsafe { extra. GetPbufferDCARB ( hbuf) } ;
75
+ if hdc. is_null ( ) {
76
+ return Err ( IoError :: last_os_error ( ) . into ( ) ) ;
77
+ }
78
+
79
+ let surface = Surface {
80
+ display : self . clone ( ) ,
81
+ config : config. clone ( ) ,
82
+ raw : WglSurface :: PBuffer ( hbuf, hdc as _ ) ,
83
+ _ty : PhantomData ,
84
+ } ;
85
+
86
+ Ok ( surface)
43
87
}
44
88
45
89
pub ( crate ) unsafe fn create_window_surface (
@@ -61,29 +105,58 @@ impl Display {
61
105
62
106
let hdc = unsafe { gdi:: GetDC ( hwnd) } ;
63
107
64
- let surface =
65
- Surface { display : self . clone ( ) , config : config. clone ( ) , hwnd, hdc, _ty : PhantomData } ;
108
+ let surface = Surface {
109
+ display : self . clone ( ) ,
110
+ config : config. clone ( ) ,
111
+ raw : WglSurface :: Window ( hwnd, hdc) ,
112
+ _ty : PhantomData ,
113
+ } ;
66
114
67
115
Ok ( surface)
68
116
}
69
117
}
70
118
71
- /// A Wrapper around `HWND `.
119
+ /// A Wrapper around `WglSurface `.
72
120
pub struct Surface < T : SurfaceTypeTrait > {
73
121
display : Display ,
74
122
config : Config ,
75
- pub ( crate ) hwnd : HWND ,
76
- pub ( crate ) hdc : HDC ,
123
+ pub ( crate ) raw : WglSurface ,
77
124
_ty : PhantomData < T > ,
78
125
}
79
126
80
127
// Impl only `Send` for Surface.
81
128
unsafe impl < T : SurfaceTypeTrait > Send for Surface < T > { }
82
129
130
+ impl < T : SurfaceTypeTrait > Surface < T > {
131
+ fn raw_attribute ( & self , attr : GLenum ) -> Option < c_int > {
132
+ match self . raw {
133
+ WglSurface :: Window ( ..) => None ,
134
+ WglSurface :: PBuffer ( hbuf, _) => {
135
+ let extra = self . display . inner . wgl_extra . unwrap ( ) ;
136
+ let mut value = 0 ;
137
+ if unsafe { extra. QueryPbufferARB ( hbuf, attr as _ , & mut value) } == false . into ( ) {
138
+ None
139
+ } else {
140
+ Some ( value)
141
+ }
142
+ } ,
143
+ }
144
+ }
145
+ }
146
+
83
147
impl < T : SurfaceTypeTrait > Drop for Surface < T > {
84
148
fn drop ( & mut self ) {
85
149
unsafe {
86
- gdi:: ReleaseDC ( self . hwnd , self . hdc ) ;
150
+ match self . raw {
151
+ WglSurface :: Window ( hwnd, hdc) => {
152
+ gdi:: ReleaseDC ( hwnd, hdc) ;
153
+ } ,
154
+ WglSurface :: PBuffer ( hbuf, hdc) => {
155
+ let extra = self . display . inner . wgl_extra . unwrap ( ) ;
156
+ extra. ReleasePbufferDCARB ( hbuf, hdc as _ ) ;
157
+ extra. DestroyPbufferARB ( hbuf) ;
158
+ } ,
159
+ }
87
160
}
88
161
}
89
162
}
@@ -97,20 +170,34 @@ impl<T: SurfaceTypeTrait> GlSurface<T> for Surface<T> {
97
170
}
98
171
99
172
fn width ( & self ) -> Option < u32 > {
100
- let mut rect: RECT = unsafe { mem:: zeroed ( ) } ;
101
- if unsafe { GetClientRect ( self . hwnd , & mut rect) } == false . into ( ) {
102
- None
103
- } else {
104
- Some ( ( rect. right - rect. left ) as u32 )
173
+ match self . raw {
174
+ WglSurface :: Window ( hwnd, _) => {
175
+ let mut rect: RECT = unsafe { mem:: zeroed ( ) } ;
176
+ if unsafe { GetClientRect ( hwnd, & mut rect) } == false . into ( ) {
177
+ None
178
+ } else {
179
+ Some ( ( rect. right - rect. left ) as u32 )
180
+ }
181
+ } ,
182
+ WglSurface :: PBuffer ( ..) => {
183
+ self . raw_attribute ( wgl_extra:: PBUFFER_WIDTH_ARB ) . map ( |x| x as _ )
184
+ } ,
105
185
}
106
186
}
107
187
108
188
fn height ( & self ) -> Option < u32 > {
109
- let mut rect: RECT = unsafe { mem:: zeroed ( ) } ;
110
- if unsafe { GetClientRect ( self . hwnd , & mut rect) } == false . into ( ) {
111
- None
112
- } else {
113
- Some ( ( rect. bottom - rect. top ) as u32 )
189
+ match self . raw {
190
+ WglSurface :: Window ( hwnd, _) => {
191
+ let mut rect: RECT = unsafe { mem:: zeroed ( ) } ;
192
+ if unsafe { GetClientRect ( hwnd, & mut rect) } == false . into ( ) {
193
+ None
194
+ } else {
195
+ Some ( ( rect. bottom - rect. top ) as u32 )
196
+ }
197
+ } ,
198
+ WglSurface :: PBuffer ( ..) => {
199
+ self . raw_attribute ( wgl_extra:: PBUFFER_HEIGHT_ARB ) . map ( |x| x as _ )
200
+ } ,
114
201
}
115
202
}
116
203
@@ -120,7 +207,7 @@ impl<T: SurfaceTypeTrait> GlSurface<T> for Surface<T> {
120
207
121
208
fn swap_buffers ( & self , _context : & Self :: Context ) -> Result < ( ) > {
122
209
unsafe {
123
- if gl:: SwapBuffers ( self . hdc ) == 0 {
210
+ if gl:: SwapBuffers ( self . raw . hdc ( ) ) == 0 {
124
211
Err ( IoError :: last_os_error ( ) . into ( ) )
125
212
} else {
126
213
Ok ( ( ) )
@@ -129,26 +216,27 @@ impl<T: SurfaceTypeTrait> GlSurface<T> for Surface<T> {
129
216
}
130
217
131
218
fn set_swap_interval ( & self , _context : & Self :: Context , interval : SwapInterval ) -> Result < ( ) > {
132
- let interval = match interval {
133
- SwapInterval :: DontWait => 0 ,
134
- SwapInterval :: Wait ( n) => n. get ( ) ,
135
- } ;
136
-
137
- let res = match self . display . inner . wgl_extra {
138
- Some ( extra) if self . display . inner . features . contains ( DisplayFeatures :: SWAP_CONTROL ) => unsafe {
139
- extra. SwapIntervalEXT ( interval as _ )
140
- } ,
141
- _ => {
142
- return Err (
143
- ErrorKind :: NotSupported ( "swap control extensions are not supported" ) . into ( )
144
- )
219
+ match self . raw {
220
+ WglSurface :: Window ( ..) => {
221
+ let extra = self
222
+ . display
223
+ . inner
224
+ . wgl_extra
225
+ . filter ( |_| self . display . inner . features . contains ( DisplayFeatures :: SWAP_CONTROL ) )
226
+ . ok_or ( ErrorKind :: NotSupported ( "swap control extensions are not supported" ) ) ?;
227
+
228
+ let interval = match interval {
229
+ SwapInterval :: DontWait => 0 ,
230
+ SwapInterval :: Wait ( n) => n. get ( ) ,
231
+ } ;
232
+
233
+ if unsafe { extra. SwapIntervalEXT ( interval as _ ) } == 0 {
234
+ Err ( IoError :: last_os_error ( ) . into ( ) )
235
+ } else {
236
+ Ok ( ( ) )
237
+ }
145
238
} ,
146
- } ;
147
-
148
- if res == 0 {
149
- Err ( IoError :: last_os_error ( ) . into ( ) )
150
- } else {
151
- Ok ( ( ) )
239
+ _ => Err ( ErrorKind :: NotSupported ( "swap control not supported for surface" ) . into ( ) ) ,
152
240
}
153
241
}
154
242
@@ -173,15 +261,17 @@ impl<T: SurfaceTypeTrait> fmt::Debug for Surface<T> {
173
261
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
174
262
f. debug_struct ( "Surface" )
175
263
. field ( "config" , & self . config . inner . pixel_format_index )
176
- . field ( "hwnd" , & self . hwnd )
177
- . field ( "hdc" , & self . hdc )
264
+ . field ( "raw" , & self . raw )
178
265
. finish ( )
179
266
}
180
267
}
181
268
182
269
impl < T : SurfaceTypeTrait > AsRawSurface for Surface < T > {
183
270
fn raw_surface ( & self ) -> RawSurface {
184
- RawSurface :: Wgl ( self . hwnd as _ )
271
+ match self . raw {
272
+ WglSurface :: Window ( hwnd, _) => RawSurface :: Wgl ( hwnd as _ ) ,
273
+ WglSurface :: PBuffer ( hbuf, _) => RawSurface :: Wgl ( hbuf as _ ) ,
274
+ }
185
275
}
186
276
}
187
277
@@ -202,3 +292,21 @@ impl<T: SurfaceTypeTrait> GetGlDisplay for Surface<T> {
202
292
}
203
293
204
294
impl < T : SurfaceTypeTrait > Sealed for Surface < T > { }
295
+
296
+ /// A wrapper around WGL surfaces.
297
+ #[ derive( Debug ) ]
298
+ pub enum WglSurface {
299
+ /// Surface backed by a window surface.
300
+ Window ( HWND , HDC ) ,
301
+ /// Surface backed by a pixel buffer.
302
+ PBuffer ( HPBUFFEREXT , HDC ) ,
303
+ }
304
+
305
+ impl WglSurface {
306
+ pub ( crate ) fn hdc ( & self ) -> HDC {
307
+ * match self {
308
+ WglSurface :: Window ( _, hdc) => hdc,
309
+ WglSurface :: PBuffer ( _, hdc) => hdc,
310
+ }
311
+ }
312
+ }
0 commit comments