Skip to content

Commit b4a3d2b

Browse files
committed
Add stubs for creating OpenGL contexts
There are now three todo!()s when compiling with the OpenGL flag that need to be filled in, with the only nontrivial one being the X11 version.
1 parent 80802df commit b4a3d2b

6 files changed

Lines changed: 118 additions & 31 deletions

File tree

examples/open_window.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ fn main() {
3636
title: "baseview".into(),
3737
size: baseview::Size::new(512.0, 512.0),
3838
scale: WindowScalePolicy::SystemScaleFactor,
39+
40+
// TODO: Add an example that uses the OpenGL context
41+
#[cfg(feature = "opengl")]
42+
gl_config: None,
3943
};
4044

4145
let (mut tx, rx) = RingBuffer::new(128);

src/macos/window.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ use crate::{
2626
use super::keyboard::KeyboardState;
2727
use super::view::{create_view, BASEVIEW_STATE_IVAR};
2828

29+
#[cfg(feature = "opengl")]
30+
use crate::gl::{GlConfig, GlContext};
31+
2932
pub struct WindowHandle {
3033
raw_window_handle: Option<RawWindowHandle>,
3134
close_requested: Arc<AtomicBool>,
@@ -102,6 +105,9 @@ pub struct Window {
102105
/// Our subclassed NSView
103106
ns_view: id,
104107
close_requested: bool,
108+
109+
#[cfg(feature = "opengl")]
110+
gl_context: Option<GlContext>,
105111
}
106112

107113
impl Window {
@@ -122,7 +128,15 @@ impl Window {
122128

123129
let ns_view = unsafe { create_view(&options) };
124130

125-
let window = Window { ns_app: None, ns_window: None, ns_view, close_requested: false };
131+
let window = Window {
132+
ns_app: None,
133+
ns_window: None,
134+
ns_view,
135+
close_requested: false,
136+
137+
#[cfg(feature = "opengl")]
138+
gl_context: options.gl_config.map(Self::create_gl_context),
139+
};
126140

127141
let window_handle = Self::init(true, window, build);
128142

@@ -146,7 +160,15 @@ impl Window {
146160

147161
let ns_view = unsafe { create_view(&options) };
148162

149-
let window = Window { ns_app: None, ns_window: None, ns_view, close_requested: false };
163+
let window = Window {
164+
ns_app: None,
165+
ns_window: None,
166+
ns_view,
167+
close_requested: false,
168+
169+
#[cfg(feature = "opengl")]
170+
gl_context: options.gl_config.map(Self::create_gl_context),
171+
};
150172

151173
let window_handle = Self::init(true, window, build);
152174

@@ -217,6 +239,9 @@ impl Window {
217239
ns_window: Some(ns_window),
218240
ns_view,
219241
close_requested: false,
242+
243+
#[cfg(feature = "opengl")]
244+
gl_context: options.gl_config.map(Self::create_gl_context),
220245
};
221246

222247
let _ = Self::init(false, window, build);
@@ -266,6 +291,16 @@ impl Window {
266291
pub fn close(&mut self) {
267292
self.close_requested = true;
268293
}
294+
295+
#[cfg(feature = "opengl")]
296+
pub fn gl_context(&self) -> Option<&GlContext> {
297+
self.gl_context.as_ref()
298+
}
299+
300+
#[cfg(feature = "opengl")]
301+
fn create_gl_context(config: GlConfig) -> GlContext {
302+
todo!("Create the macOS OpenGL context");
303+
}
269304
}
270305

271306
pub(super) struct WindowState {

src/win/window.rs

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ use crate::{
3434

3535
use super::keyboard::KeyboardState;
3636

37+
#[cfg(feature = "opengl")]
38+
use crate::gl::GlContext;
39+
3740
unsafe fn generate_guid() -> String {
3841
let mut guid: GUID = std::mem::zeroed();
3942
CoCreateGuid(&mut guid);
@@ -124,7 +127,9 @@ unsafe extern "system" fn wnd_proc(
124127

125128
let window_state_ptr = GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut RefCell<WindowState>;
126129
if !window_state_ptr.is_null() {
127-
let mut window = Window { hwnd };
130+
let mut window_state = (*window_state_ptr).borrow_mut();
131+
132+
let mut window = window_state.create_window(hwnd);
128133
let mut window = crate::Window::new(&mut window);
129134

130135
match msg {
@@ -134,8 +139,6 @@ unsafe extern "system" fn wnd_proc(
134139

135140
let physical_pos = PhyPoint { x, y };
136141

137-
let mut window_state = (&*window_state_ptr).borrow_mut();
138-
139142
let logical_pos = physical_pos.to_logical(&window_state.window_info);
140143

141144
window_state.handler.on_event(
@@ -149,8 +152,6 @@ unsafe extern "system" fn wnd_proc(
149152
let value = value as i32;
150153
let value = value as f32 / WHEEL_DELTA as f32;
151154

152-
let mut window_state = (&*window_state_ptr).borrow_mut();
153-
154155
window_state.handler.on_event(
155156
&mut window,
156157
Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines {
@@ -162,7 +163,7 @@ unsafe extern "system" fn wnd_proc(
162163
}
163164
WM_LBUTTONDOWN | WM_LBUTTONUP | WM_MBUTTONDOWN | WM_MBUTTONUP | WM_RBUTTONDOWN
164165
| WM_RBUTTONUP | WM_XBUTTONDOWN | WM_XBUTTONUP => {
165-
let mut mouse_button_counter = (&*window_state_ptr).borrow().mouse_button_counter;
166+
let mut mouse_button_counter = (*window_state_ptr).borrow().mouse_button_counter;
166167

167168
let button = match msg {
168169
WM_LBUTTONDOWN | WM_LBUTTONUP => Some(MouseButton::Left),
@@ -198,44 +199,33 @@ unsafe extern "system" fn wnd_proc(
198199
}
199200
};
200201

201-
(&*window_state_ptr).borrow_mut().mouse_button_counter = mouse_button_counter;
202+
window_state.mouse_button_counter = mouse_button_counter;
202203

203-
(&*window_state_ptr)
204-
.borrow_mut()
205-
.handler
206-
.on_event(&mut window, Event::Mouse(event));
204+
window_state.handler.on_event(&mut window, Event::Mouse(event));
207205
}
208206
}
209207
WM_TIMER => {
210208
match wparam {
211209
WIN_FRAME_TIMER => {
212-
(&*window_state_ptr).borrow_mut().handler.on_frame(&mut window);
210+
window_state.handler.on_frame(&mut window);
213211
}
214212
_ => (),
215213
}
216214
return 0;
217215
}
218216
WM_CLOSE => {
219-
(&*window_state_ptr)
220-
.borrow_mut()
221-
.handler
222-
.on_event(&mut window, Event::Window(WindowEvent::WillClose));
217+
window_state.handler.on_event(&mut window, Event::Window(WindowEvent::WillClose));
223218
// DestroyWindow(hwnd);
224219
// return 0;
225220
return DefWindowProcW(hwnd, msg, wparam, lparam);
226221
}
227222
WM_CHAR | WM_SYSCHAR | WM_KEYDOWN | WM_SYSKEYDOWN | WM_KEYUP | WM_SYSKEYUP
228223
| WM_INPUTLANGCHANGE => {
229-
let opt_event = (&*window_state_ptr)
230-
.borrow_mut()
231-
.keyboard_state
232-
.process_message(hwnd, msg, wparam, lparam);
224+
let opt_event =
225+
window_state.keyboard_state.process_message(hwnd, msg, wparam, lparam);
233226

234227
if let Some(event) = opt_event {
235-
(&*window_state_ptr)
236-
.borrow_mut()
237-
.handler
238-
.on_event(&mut window, Event::Keyboard(event));
228+
window_state.handler.on_event(&mut window, Event::Keyboard(event));
239229
}
240230

241231
if msg != WM_SYSKEYDOWN {
@@ -246,8 +236,6 @@ unsafe extern "system" fn wnd_proc(
246236
let width = (lparam & 0xFFFF) as u16 as u32;
247237
let height = ((lparam >> 16) & 0xFFFF) as u16 as u32;
248238

249-
let mut window_state = (&*window_state_ptr).borrow_mut();
250-
251239
window_state.window_info = WindowInfo::from_physical_size(
252240
PhySize { width, height },
253241
window_state.window_info.scale(),
@@ -262,8 +250,6 @@ unsafe extern "system" fn wnd_proc(
262250
WM_DPICHANGED => {
263251
// To avoid weirdness with the realtime borrow checker.
264252
let new_rect = {
265-
let mut window_state = (&*window_state_ptr).borrow_mut();
266-
267253
if let WindowScalePolicy::SystemScaleFactor = window_state.scale_policy {
268254
let dpi = (wparam & 0xFFFF) as u16 as u32;
269255
let scale_factor = dpi as f64 / 96.0;
@@ -319,7 +305,7 @@ unsafe extern "system" fn wnd_proc(
319305
}
320306
}
321307

322-
return DefWindowProcW(hwnd, msg, wparam, lparam);
308+
DefWindowProcW(hwnd, msg, wparam, lparam)
323309
}
324310

325311
unsafe fn register_wnd_class() -> ATOM {
@@ -357,10 +343,28 @@ struct WindowState {
357343
handler: Box<dyn WindowHandler>,
358344
scale_policy: WindowScalePolicy,
359345
dw_style: u32,
346+
347+
#[cfg(feature = "opengl")]
348+
gl_context: Arc<Option<GlContext>>,
349+
}
350+
351+
impl WindowState {
352+
#[cfg(not(feature = "opengl"))]
353+
fn create_window(&self, hwnd: HWND) -> Window {
354+
Window { hwnd }
355+
}
356+
357+
#[cfg(feature = "opengl")]
358+
fn create_window(&self, hwnd: HWND) -> Window {
359+
Window { hwnd, gl_context: self.gl_context.clone() }
360+
}
360361
}
361362

362363
pub struct Window {
363364
hwnd: HWND,
365+
366+
#[cfg(feature = "opengl")]
367+
gl_context: Arc<Option<GlContext>>,
364368
}
365369

366370
impl Window {
@@ -478,7 +482,17 @@ impl Window {
478482
);
479483
// todo: manage error ^
480484

485+
#[cfg(feature = "opengl")]
486+
let gl_context: Arc<Option<GlContext>> =
487+
Arc::new(todo!("Create the Windows OpenGL context"));
488+
489+
#[cfg(not(feature = "opengl"))]
481490
let handler = Box::new(build(&mut crate::Window::new(&mut Window { hwnd })));
491+
#[cfg(feature = "opengl")]
492+
let handler = Box::new(build(&mut crate::Window::new(&mut Window {
493+
hwnd,
494+
gl_context: gl_context.clone(),
495+
})));
482496

483497
let (parent_handle, window_handle) = ParentHandle::new(hwnd);
484498
let parent_handle = if parented { Some(parent_handle) } else { None };
@@ -492,6 +506,9 @@ impl Window {
492506
handler,
493507
scale_policy: options.scale,
494508
dw_style: flags,
509+
510+
#[cfg(feature = "opengl")]
511+
gl_context,
495512
}));
496513

497514
// Only works on Windows 10 unfortunately.
@@ -556,6 +573,11 @@ impl Window {
556573
PostMessageW(self.hwnd, BV_WINDOW_MUST_CLOSE, 0, 0);
557574
}
558575
}
576+
577+
#[cfg(feature = "opengl")]
578+
pub fn gl_context(&self) -> Option<&GlContext> {
579+
self.gl_context.as_ref().as_ref()
580+
}
559581
}
560582

561583
unsafe impl HasRawWindowHandle for Window {

src/window.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ impl<'a> Window<'a> {
9191
pub fn close(&mut self) {
9292
self.window.close();
9393
}
94+
95+
/// If provided, then an OpenGL context will be created for this window. You'll be able to
96+
/// access this context through [crate::Window::gl_context].
97+
#[cfg(feature = "opengl")]
98+
pub fn gl_context(&self) -> Option<&crate::gl::GlContext> {
99+
self.window.gl_context()
100+
}
94101
}
95102

96103
unsafe impl<'a> HasRawWindowHandle for Window<'a> {

src/window_open_options.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,9 @@ pub struct WindowOpenOptions {
2121

2222
/// The dpi scaling policy
2323
pub scale: WindowScalePolicy,
24+
25+
/// If provided, then an OpenGL context will be created for this window. You'll be able to
26+
/// access this context through [crate::Window::gl_context].
27+
#[cfg(feature = "opengl")]
28+
pub gl_config: Option<crate::gl::GlConfig>,
2429
}

src/x11/window.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ use crate::{
1616

1717
use super::keyboard::{convert_key_press_event, convert_key_release_event};
1818

19+
#[cfg(feature = "opengl")]
20+
use crate::gl::GlContext;
21+
1922
pub struct WindowHandle {
2023
raw_window_handle: Option<RawWindowHandle>,
2124
close_requested: Arc<AtomicBool>,
@@ -96,6 +99,9 @@ pub struct Window {
9699

97100
new_physical_size: Option<PhySize>,
98101
parent_handle: Option<ParentHandle>,
102+
103+
#[cfg(feature = "opengl")]
104+
gl_context: Option<GlContext>,
99105
}
100106

101107
// Hack to allow sending a RawWindowHandle between threads. Do not make public
@@ -306,6 +312,9 @@ impl Window {
306312

307313
new_physical_size: None,
308314
parent_handle,
315+
316+
#[cfg(feature = "opengl")]
317+
gl_context: todo!("Create the X11 OpenGL context"),
309318
};
310319

311320
let mut handler = build(&mut crate::Window::new(&mut window));
@@ -346,6 +355,11 @@ impl Window {
346355
self.close_requested = true;
347356
}
348357

358+
#[cfg(feature = "opengl")]
359+
pub fn gl_context(&self) -> Option<&crate::gl::GlContext> {
360+
self.gl_context.as_ref()
361+
}
362+
349363
#[inline]
350364
fn drain_xcb_events(&mut self, handler: &mut dyn WindowHandler) {
351365
// the X server has a tendency to send spurious/extraneous configure notify events when a

0 commit comments

Comments
 (0)