1
0
Fork 0

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.
This commit is contained in:
Robbert van der Helm 2022-02-07 19:00:03 +01:00
parent 80802dfbe9
commit b4a3d2bb04
6 changed files with 118 additions and 31 deletions

View file

@ -36,6 +36,10 @@ fn main() {
title: "baseview".into(), title: "baseview".into(),
size: baseview::Size::new(512.0, 512.0), size: baseview::Size::new(512.0, 512.0),
scale: WindowScalePolicy::SystemScaleFactor, scale: WindowScalePolicy::SystemScaleFactor,
// TODO: Add an example that uses the OpenGL context
#[cfg(feature = "opengl")]
gl_config: None,
}; };
let (mut tx, rx) = RingBuffer::new(128); let (mut tx, rx) = RingBuffer::new(128);

View file

@ -26,6 +26,9 @@ use crate::{
use super::keyboard::KeyboardState; use super::keyboard::KeyboardState;
use super::view::{create_view, BASEVIEW_STATE_IVAR}; use super::view::{create_view, BASEVIEW_STATE_IVAR};
#[cfg(feature = "opengl")]
use crate::gl::{GlConfig, GlContext};
pub struct WindowHandle { pub struct WindowHandle {
raw_window_handle: Option<RawWindowHandle>, raw_window_handle: Option<RawWindowHandle>,
close_requested: Arc<AtomicBool>, close_requested: Arc<AtomicBool>,
@ -102,6 +105,9 @@ pub struct Window {
/// Our subclassed NSView /// Our subclassed NSView
ns_view: id, ns_view: id,
close_requested: bool, close_requested: bool,
#[cfg(feature = "opengl")]
gl_context: Option<GlContext>,
} }
impl Window { impl Window {
@ -122,7 +128,15 @@ impl Window {
let ns_view = unsafe { create_view(&options) }; let ns_view = unsafe { create_view(&options) };
let window = Window { ns_app: None, ns_window: None, ns_view, close_requested: false }; let window = Window {
ns_app: None,
ns_window: None,
ns_view,
close_requested: false,
#[cfg(feature = "opengl")]
gl_context: options.gl_config.map(Self::create_gl_context),
};
let window_handle = Self::init(true, window, build); let window_handle = Self::init(true, window, build);
@ -146,7 +160,15 @@ impl Window {
let ns_view = unsafe { create_view(&options) }; let ns_view = unsafe { create_view(&options) };
let window = Window { ns_app: None, ns_window: None, ns_view, close_requested: false }; let window = Window {
ns_app: None,
ns_window: None,
ns_view,
close_requested: false,
#[cfg(feature = "opengl")]
gl_context: options.gl_config.map(Self::create_gl_context),
};
let window_handle = Self::init(true, window, build); let window_handle = Self::init(true, window, build);
@ -217,6 +239,9 @@ impl Window {
ns_window: Some(ns_window), ns_window: Some(ns_window),
ns_view, ns_view,
close_requested: false, close_requested: false,
#[cfg(feature = "opengl")]
gl_context: options.gl_config.map(Self::create_gl_context),
}; };
let _ = Self::init(false, window, build); let _ = Self::init(false, window, build);
@ -266,6 +291,16 @@ impl Window {
pub fn close(&mut self) { pub fn close(&mut self) {
self.close_requested = true; self.close_requested = true;
} }
#[cfg(feature = "opengl")]
pub fn gl_context(&self) -> Option<&GlContext> {
self.gl_context.as_ref()
}
#[cfg(feature = "opengl")]
fn create_gl_context(config: GlConfig) -> GlContext {
todo!("Create the macOS OpenGL context");
}
} }
pub(super) struct WindowState { pub(super) struct WindowState {

View file

@ -34,6 +34,9 @@ use crate::{
use super::keyboard::KeyboardState; use super::keyboard::KeyboardState;
#[cfg(feature = "opengl")]
use crate::gl::GlContext;
unsafe fn generate_guid() -> String { unsafe fn generate_guid() -> String {
let mut guid: GUID = std::mem::zeroed(); let mut guid: GUID = std::mem::zeroed();
CoCreateGuid(&mut guid); CoCreateGuid(&mut guid);
@ -124,7 +127,9 @@ unsafe extern "system" fn wnd_proc(
let window_state_ptr = GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut RefCell<WindowState>; let window_state_ptr = GetWindowLongPtrW(hwnd, GWLP_USERDATA) as *mut RefCell<WindowState>;
if !window_state_ptr.is_null() { if !window_state_ptr.is_null() {
let mut window = Window { hwnd }; let mut window_state = (*window_state_ptr).borrow_mut();
let mut window = window_state.create_window(hwnd);
let mut window = crate::Window::new(&mut window); let mut window = crate::Window::new(&mut window);
match msg { match msg {
@ -134,8 +139,6 @@ unsafe extern "system" fn wnd_proc(
let physical_pos = PhyPoint { x, y }; let physical_pos = PhyPoint { x, y };
let mut window_state = (&*window_state_ptr).borrow_mut();
let logical_pos = physical_pos.to_logical(&window_state.window_info); let logical_pos = physical_pos.to_logical(&window_state.window_info);
window_state.handler.on_event( window_state.handler.on_event(
@ -149,8 +152,6 @@ unsafe extern "system" fn wnd_proc(
let value = value as i32; let value = value as i32;
let value = value as f32 / WHEEL_DELTA as f32; let value = value as f32 / WHEEL_DELTA as f32;
let mut window_state = (&*window_state_ptr).borrow_mut();
window_state.handler.on_event( window_state.handler.on_event(
&mut window, &mut window,
Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines { Event::Mouse(MouseEvent::WheelScrolled(ScrollDelta::Lines {
@ -162,7 +163,7 @@ unsafe extern "system" fn wnd_proc(
} }
WM_LBUTTONDOWN | WM_LBUTTONUP | WM_MBUTTONDOWN | WM_MBUTTONUP | WM_RBUTTONDOWN WM_LBUTTONDOWN | WM_LBUTTONUP | WM_MBUTTONDOWN | WM_MBUTTONUP | WM_RBUTTONDOWN
| WM_RBUTTONUP | WM_XBUTTONDOWN | WM_XBUTTONUP => { | WM_RBUTTONUP | WM_XBUTTONDOWN | WM_XBUTTONUP => {
let mut mouse_button_counter = (&*window_state_ptr).borrow().mouse_button_counter; let mut mouse_button_counter = (*window_state_ptr).borrow().mouse_button_counter;
let button = match msg { let button = match msg {
WM_LBUTTONDOWN | WM_LBUTTONUP => Some(MouseButton::Left), WM_LBUTTONDOWN | WM_LBUTTONUP => Some(MouseButton::Left),
@ -198,44 +199,33 @@ unsafe extern "system" fn wnd_proc(
} }
}; };
(&*window_state_ptr).borrow_mut().mouse_button_counter = mouse_button_counter; window_state.mouse_button_counter = mouse_button_counter;
(&*window_state_ptr) window_state.handler.on_event(&mut window, Event::Mouse(event));
.borrow_mut()
.handler
.on_event(&mut window, Event::Mouse(event));
} }
} }
WM_TIMER => { WM_TIMER => {
match wparam { match wparam {
WIN_FRAME_TIMER => { WIN_FRAME_TIMER => {
(&*window_state_ptr).borrow_mut().handler.on_frame(&mut window); window_state.handler.on_frame(&mut window);
} }
_ => (), _ => (),
} }
return 0; return 0;
} }
WM_CLOSE => { WM_CLOSE => {
(&*window_state_ptr) window_state.handler.on_event(&mut window, Event::Window(WindowEvent::WillClose));
.borrow_mut()
.handler
.on_event(&mut window, Event::Window(WindowEvent::WillClose));
// DestroyWindow(hwnd); // DestroyWindow(hwnd);
// return 0; // return 0;
return DefWindowProcW(hwnd, msg, wparam, lparam); return DefWindowProcW(hwnd, msg, wparam, lparam);
} }
WM_CHAR | WM_SYSCHAR | WM_KEYDOWN | WM_SYSKEYDOWN | WM_KEYUP | WM_SYSKEYUP WM_CHAR | WM_SYSCHAR | WM_KEYDOWN | WM_SYSKEYDOWN | WM_KEYUP | WM_SYSKEYUP
| WM_INPUTLANGCHANGE => { | WM_INPUTLANGCHANGE => {
let opt_event = (&*window_state_ptr) let opt_event =
.borrow_mut() window_state.keyboard_state.process_message(hwnd, msg, wparam, lparam);
.keyboard_state
.process_message(hwnd, msg, wparam, lparam);
if let Some(event) = opt_event { if let Some(event) = opt_event {
(&*window_state_ptr) window_state.handler.on_event(&mut window, Event::Keyboard(event));
.borrow_mut()
.handler
.on_event(&mut window, Event::Keyboard(event));
} }
if msg != WM_SYSKEYDOWN { if msg != WM_SYSKEYDOWN {
@ -246,8 +236,6 @@ unsafe extern "system" fn wnd_proc(
let width = (lparam & 0xFFFF) as u16 as u32; let width = (lparam & 0xFFFF) as u16 as u32;
let height = ((lparam >> 16) & 0xFFFF) as u16 as u32; let height = ((lparam >> 16) & 0xFFFF) as u16 as u32;
let mut window_state = (&*window_state_ptr).borrow_mut();
window_state.window_info = WindowInfo::from_physical_size( window_state.window_info = WindowInfo::from_physical_size(
PhySize { width, height }, PhySize { width, height },
window_state.window_info.scale(), window_state.window_info.scale(),
@ -262,8 +250,6 @@ unsafe extern "system" fn wnd_proc(
WM_DPICHANGED => { WM_DPICHANGED => {
// To avoid weirdness with the realtime borrow checker. // To avoid weirdness with the realtime borrow checker.
let new_rect = { let new_rect = {
let mut window_state = (&*window_state_ptr).borrow_mut();
if let WindowScalePolicy::SystemScaleFactor = window_state.scale_policy { if let WindowScalePolicy::SystemScaleFactor = window_state.scale_policy {
let dpi = (wparam & 0xFFFF) as u16 as u32; let dpi = (wparam & 0xFFFF) as u16 as u32;
let scale_factor = dpi as f64 / 96.0; let scale_factor = dpi as f64 / 96.0;
@ -319,7 +305,7 @@ unsafe extern "system" fn wnd_proc(
} }
} }
return DefWindowProcW(hwnd, msg, wparam, lparam); DefWindowProcW(hwnd, msg, wparam, lparam)
} }
unsafe fn register_wnd_class() -> ATOM { unsafe fn register_wnd_class() -> ATOM {
@ -357,10 +343,28 @@ struct WindowState {
handler: Box<dyn WindowHandler>, handler: Box<dyn WindowHandler>,
scale_policy: WindowScalePolicy, scale_policy: WindowScalePolicy,
dw_style: u32, dw_style: u32,
#[cfg(feature = "opengl")]
gl_context: Arc<Option<GlContext>>,
}
impl WindowState {
#[cfg(not(feature = "opengl"))]
fn create_window(&self, hwnd: HWND) -> Window {
Window { hwnd }
}
#[cfg(feature = "opengl")]
fn create_window(&self, hwnd: HWND) -> Window {
Window { hwnd, gl_context: self.gl_context.clone() }
}
} }
pub struct Window { pub struct Window {
hwnd: HWND, hwnd: HWND,
#[cfg(feature = "opengl")]
gl_context: Arc<Option<GlContext>>,
} }
impl Window { impl Window {
@ -478,7 +482,17 @@ impl Window {
); );
// todo: manage error ^ // todo: manage error ^
#[cfg(feature = "opengl")]
let gl_context: Arc<Option<GlContext>> =
Arc::new(todo!("Create the Windows OpenGL context"));
#[cfg(not(feature = "opengl"))]
let handler = Box::new(build(&mut crate::Window::new(&mut Window { hwnd }))); let handler = Box::new(build(&mut crate::Window::new(&mut Window { hwnd })));
#[cfg(feature = "opengl")]
let handler = Box::new(build(&mut crate::Window::new(&mut Window {
hwnd,
gl_context: gl_context.clone(),
})));
let (parent_handle, window_handle) = ParentHandle::new(hwnd); let (parent_handle, window_handle) = ParentHandle::new(hwnd);
let parent_handle = if parented { Some(parent_handle) } else { None }; let parent_handle = if parented { Some(parent_handle) } else { None };
@ -492,6 +506,9 @@ impl Window {
handler, handler,
scale_policy: options.scale, scale_policy: options.scale,
dw_style: flags, dw_style: flags,
#[cfg(feature = "opengl")]
gl_context,
})); }));
// Only works on Windows 10 unfortunately. // Only works on Windows 10 unfortunately.
@ -556,6 +573,11 @@ impl Window {
PostMessageW(self.hwnd, BV_WINDOW_MUST_CLOSE, 0, 0); PostMessageW(self.hwnd, BV_WINDOW_MUST_CLOSE, 0, 0);
} }
} }
#[cfg(feature = "opengl")]
pub fn gl_context(&self) -> Option<&GlContext> {
self.gl_context.as_ref().as_ref()
}
} }
unsafe impl HasRawWindowHandle for Window { unsafe impl HasRawWindowHandle for Window {

View file

@ -91,6 +91,13 @@ impl<'a> Window<'a> {
pub fn close(&mut self) { pub fn close(&mut self) {
self.window.close(); self.window.close();
} }
/// If provided, then an OpenGL context will be created for this window. You'll be able to
/// access this context through [crate::Window::gl_context].
#[cfg(feature = "opengl")]
pub fn gl_context(&self) -> Option<&crate::gl::GlContext> {
self.window.gl_context()
}
} }
unsafe impl<'a> HasRawWindowHandle for Window<'a> { unsafe impl<'a> HasRawWindowHandle for Window<'a> {

View file

@ -21,4 +21,9 @@ pub struct WindowOpenOptions {
/// The dpi scaling policy /// The dpi scaling policy
pub scale: WindowScalePolicy, pub scale: WindowScalePolicy,
/// If provided, then an OpenGL context will be created for this window. You'll be able to
/// access this context through [crate::Window::gl_context].
#[cfg(feature = "opengl")]
pub gl_config: Option<crate::gl::GlConfig>,
} }

View file

@ -16,6 +16,9 @@ use crate::{
use super::keyboard::{convert_key_press_event, convert_key_release_event}; use super::keyboard::{convert_key_press_event, convert_key_release_event};
#[cfg(feature = "opengl")]
use crate::gl::GlContext;
pub struct WindowHandle { pub struct WindowHandle {
raw_window_handle: Option<RawWindowHandle>, raw_window_handle: Option<RawWindowHandle>,
close_requested: Arc<AtomicBool>, close_requested: Arc<AtomicBool>,
@ -96,6 +99,9 @@ pub struct Window {
new_physical_size: Option<PhySize>, new_physical_size: Option<PhySize>,
parent_handle: Option<ParentHandle>, parent_handle: Option<ParentHandle>,
#[cfg(feature = "opengl")]
gl_context: Option<GlContext>,
} }
// Hack to allow sending a RawWindowHandle between threads. Do not make public // Hack to allow sending a RawWindowHandle between threads. Do not make public
@ -306,6 +312,9 @@ impl Window {
new_physical_size: None, new_physical_size: None,
parent_handle, parent_handle,
#[cfg(feature = "opengl")]
gl_context: todo!("Create the X11 OpenGL context"),
}; };
let mut handler = build(&mut crate::Window::new(&mut window)); let mut handler = build(&mut crate::Window::new(&mut window));
@ -346,6 +355,11 @@ impl Window {
self.close_requested = true; self.close_requested = true;
} }
#[cfg(feature = "opengl")]
pub fn gl_context(&self) -> Option<&crate::gl::GlContext> {
self.gl_context.as_ref()
}
#[inline] #[inline]
fn drain_xcb_events(&mut self, handler: &mut dyn WindowHandler) { fn drain_xcb_events(&mut self, handler: &mut dyn WindowHandler) {
// the X server has a tendency to send spurious/extraneous configure notify events when a // the X server has a tendency to send spurious/extraneous configure notify events when a