Skip to content

Commit be0d913

Browse files
committed
wip
1 parent 3863d6b commit be0d913

4 files changed

Lines changed: 121 additions & 80 deletions

File tree

examples/plugin_clack/src/gui.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::window_handler::OpenWindowExample;
22
use crate::ExamplePluginMainThread;
33
use baseview::dpi::PhysicalSize;
44
use baseview::gl::GlConfig;
5-
use baseview::{Window, WindowHandle, WindowOpenOptions};
5+
use baseview::{WindowHandle, WindowOpenOptions};
66
use clack_extensions::gui::{
77
GuiApiType, GuiConfiguration, GuiResizeHints, GuiSize, PluginGuiImpl, Window as ClapWindow,
88
};
@@ -72,9 +72,10 @@ impl PluginGuiImpl for ExamplePluginMainThread {
7272

7373
let options = WindowOpenOptions::new()
7474
.with_size(PhysicalSize::new(400, 200))
75-
.with_gl_config(GlConfig::default());
75+
.with_gl_config(GlConfig::default())
76+
.with_parent(&parent);
7677

77-
let window = Window::open_parented(&parent, options, OpenWindowExample::new);
78+
let window = baseview::create_window(options, OpenWindowExample::new)?;
7879

7980
self.gui = Some(ExamplePluginGui { handle: window });
8081

examples/plugin_clack/src/window_handler.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use baseview::dpi::PhysicalPosition;
2-
use baseview::{Event, EventStatus, MouseEvent, WindowContext, WindowHandler, WindowSize};
2+
use baseview::{
3+
Event, EventStatus, HandlerError, MouseEvent, WindowContext, WindowHandler, WindowSize,
4+
};
35
use std::cell::{Cell, RefCell};
46
use std::num::NonZeroU32;
57

@@ -115,21 +117,20 @@ impl WindowHandler for OpenWindowExample {
115117
}
116118

117119
impl OpenWindowExample {
118-
pub fn new(window: WindowContext) -> Self {
119-
let ctx = softbuffer::Context::new(window.clone()).unwrap();
120-
let mut surface = softbuffer::Surface::new(&ctx, window.clone()).unwrap();
120+
pub fn new(window: WindowContext) -> Result<Self, HandlerError> {
121+
let ctx = softbuffer::Context::new(window.clone())?;
122+
let mut surface = softbuffer::Surface::new(&ctx, window.clone())?;
121123
let size = window.size().physical;
122124
surface
123-
.resize(NonZeroU32::new(size.width).unwrap(), NonZeroU32::new(size.height).unwrap())
124-
.unwrap();
125+
.resize(NonZeroU32::new(size.width).unwrap(), NonZeroU32::new(size.height).unwrap())?;
125126

126-
OpenWindowExample {
127+
Ok(OpenWindowExample {
127128
window_context: window,
128129
surface: surface.into(),
129130
mouse_pos: PhysicalPosition::new(0., 0.).into(),
130131
is_cursor_inside: false.into(),
131132
damaged: true.into(),
132-
}
133+
})
133134
}
134135
}
135136

src/platform/win/gl.rs

Lines changed: 29 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,23 @@ use windows_core::{s, PCSTR};
55
use windows_sys::Win32::Graphics::OpenGL::wglGetProcAddress;
66

77
use crate::gl::*;
8+
use crate::tracing::warn;
89
use crate::wrappers::win32::window::{
9-
with_dummy_window, HWnd, MissingExtensionFunctionError, OwnDeviceContext, PixelFormat,
10-
PixelFormatAttribs, WglContext, WglExtra,
10+
with_dummy_window, HWnd, OwnDeviceContext, PixelFormat, PixelFormatAttribs, WglContext,
11+
WglExtra,
1112
};
1213
use crate::wrappers::win32::LibraryModule;
1314

14-
#[derive(Debug)]
15-
pub enum CreationFailedError {
16-
Win32(windows_core::Error),
17-
MissingWglExtension(MissingExtensionFunctionError),
18-
}
19-
20-
impl From<windows_core::Error> for CreationFailedError {
21-
fn from(err: windows_core::Error) -> Self {
22-
CreationFailedError::Win32(err)
23-
}
24-
}
25-
26-
impl From<MissingExtensionFunctionError> for CreationFailedError {
27-
fn from(err: MissingExtensionFunctionError) -> Self {
28-
CreationFailedError::MissingWglExtension(err)
29-
}
30-
}
31-
3215
pub type GlContext = Rc<GlContextInner>;
3316

34-
impl From<CreationFailedError> for GlError {
35-
fn from(e: CreationFailedError) -> Self {
36-
GlError::CreationFailed(e)
37-
}
38-
}
39-
4017
pub struct GlContextInner {
4118
hdc: OwnDeviceContext,
4219
wgl_ctx: WglContext,
4320
gl_library: LibraryModule,
4421
}
4522

4623
impl GlContextInner {
47-
pub fn create(window: HWnd, config: GlConfig) -> Result<Self, CreationFailedError> {
24+
pub fn create(window: HWnd, config: GlConfig) -> Result<Self, windows_core::Error> {
4825
let gl_library = unsafe { LibraryModule::load(s!("opengl32.dll"))? };
4926

5027
// Create temporary window and context to load function pointers
@@ -54,7 +31,7 @@ impl GlContextInner {
5431

5532
let wgl_ctx = hdc.create_wgl_context()?;
5633
wgl_ctx.with_current(&hdc, WglExtra::load)
57-
})??;
34+
})?;
5835

5936
// Create actual context
6037
let hdc = window.get_own_dc()?;
@@ -64,9 +41,17 @@ impl GlContextInner {
6441
None => hdc.set_pixel_format(&PixelFormat::from_config(&config))?,
6542
}
6643

67-
let wgl_ctx = extra.create_context_for_config(&hdc, &config)?;
44+
let wgl_ctx = match extra.create_context_for_config(&hdc, &config) {
45+
Ok(wgl_ctx) => wgl_ctx,
46+
Err(e) => {
47+
warn!("Could not create OpenGL context from OpenGL config attributes: {}. Attempting fallback.", e);
48+
hdc.create_wgl_context()?
49+
}
50+
};
6851

69-
wgl_ctx.with_current(&hdc, || extra.set_vsync(config.vsync))??;
52+
if let Err(e) | Ok(Err(e)) = wgl_ctx.with_current(&hdc, || extra.set_vsync(config.vsync)) {
53+
warn!("Could not set vsync: {}", e);
54+
}
7055

7156
Ok(Self { hdc, wgl_ctx, gl_library })
7257
}
@@ -104,16 +89,25 @@ fn find_wgl_pixel_format(
10489
) -> Option<NonZeroI32> {
10590
let mut format_attribs = PixelFormatAttribs::from_config(config);
10691

107-
// TODO: log errors
108-
if let Ok(Some(format)) = extra.choose_pixel_format_from_attribs(&format_attribs, dc) {
109-
return Some(format);
92+
match extra.choose_pixel_format_from_attribs(&format_attribs, dc) {
93+
Ok(Some(format)) => return Some(format),
94+
Err(e) => {
95+
warn!("Could not choose optimal pixel format from GL configuration: {}", e);
96+
return None;
97+
}
98+
Ok(None) => {}
11099
};
111100

112101
eprintln!("Warning: sRGB framebuffer not supported, falling back to non-sRGB");
113102
format_attribs.set_without_srgb_ext();
114103

115-
if let Ok(Some(format)) = extra.choose_pixel_format_from_attribs(&format_attribs, dc) {
116-
return Some(format);
104+
match extra.choose_pixel_format_from_attribs(&format_attribs, dc) {
105+
Ok(Some(format)) => return Some(format),
106+
Err(e) => {
107+
warn!("Could not choose optimal pixel format from GL configuration: {}", e);
108+
return None;
109+
}
110+
Ok(None) => {}
117111
};
118112

119113
None

src/wrappers/win32/window/wgl.rs

Lines changed: 79 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1+
#![allow(non_snake_case)]
2+
13
use crate::gl::{GlConfig, Profile};
4+
use crate::tracing::warn;
25
use crate::wrappers::win32::window::OwnDeviceContext;
36
use std::ffi::{c_void, CStr};
47
use std::fmt::{Display, Formatter};
58
use std::mem::transmute;
69
use std::num::NonZeroI32;
710
use std::ptr::{null_mut, NonNull};
811
use windows_core::Error;
12+
use windows_sys::s;
13+
use windows_sys::Win32::Foundation::PROC;
914
use windows_sys::Win32::Graphics::Gdi::HDC;
1015
use windows_sys::Win32::Graphics::OpenGL::{
1116
wglDeleteContext, wglGetCurrentContext, wglGetProcAddress, wglMakeCurrent, HGLRC,
@@ -74,8 +79,14 @@ impl WglContext {
7479

7580
impl Drop for WglContext {
7681
fn drop(&mut self) {
77-
let _ = unsafe { self.make_not_current() };
78-
unsafe { wglDeleteContext(self.inner.as_ptr()) }; // TODO: warn on error
82+
if let Err(e) = unsafe { self.make_not_current() } {
83+
warn!("Could not unset current GL context {}", e);
84+
}
85+
86+
let result = unsafe { wglDeleteContext(self.inner.as_ptr()) };
87+
if result == 0 {
88+
warn!("Could not delete GL context: {}", Error::from_thread());
89+
}
7990
}
8091
}
8192

@@ -89,42 +100,35 @@ type WglChoosePixelFormatARB =
89100
// See https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_create_context.txt
90101
type WglCreateContextAttribsARB = unsafe extern "system" fn(HDC, HGLRC, *const i32) -> HGLRC;
91102

92-
#[allow(non_snake_case)]
93103
pub struct WglExtra {
94-
wglCreateContextAttribsARB: WglCreateContextAttribsARB,
95-
wglChoosePixelFormatARB: WglChoosePixelFormatARB,
96-
wglSwapIntervalEXT: WglSwapIntervalEXT,
104+
wglCreateContextAttribsARB: Option<WglCreateContextAttribsARB>,
105+
wglChoosePixelFormatARB: Option<WglChoosePixelFormatARB>,
106+
wglSwapIntervalEXT: Option<WglSwapIntervalEXT>,
97107
}
98108

99109
impl WglExtra {
100-
pub fn load() -> Result<Self, MissingExtensionFunctionError> {
110+
pub fn load() -> Self {
101111
unsafe {
102-
Ok(Self {
103-
wglCreateContextAttribsARB: transmute::<*const c_void, WglCreateContextAttribsARB>(
104-
Self::load_fn(c"wglCreateContextAttribsARB")?,
112+
Self {
113+
wglCreateContextAttribsARB: transmute::<PROC, Option<WglCreateContextAttribsARB>>(
114+
wglGetProcAddress(s!("wglCreateContextAttribsARB")),
105115
),
106-
wglChoosePixelFormatARB: transmute::<*const c_void, WglChoosePixelFormatARB>(
107-
Self::load_fn(c"wglChoosePixelFormatARB")?,
116+
wglChoosePixelFormatARB: transmute::<PROC, Option<WglChoosePixelFormatARB>>(
117+
wglGetProcAddress(s!("wglChoosePixelFormatARB")),
108118
),
109-
wglSwapIntervalEXT: transmute::<*const c_void, WglSwapIntervalEXT>(Self::load_fn(
110-
c"wglSwapIntervalEXT",
111-
)?),
112-
})
113-
}
114-
}
115-
116-
fn load_fn(name: &'static CStr) -> Result<*const c_void, MissingExtensionFunctionError> {
117-
let ptr = unsafe { wglGetProcAddress(name.as_ptr() as *const u8) };
118-
119-
match ptr {
120-
Some(ptr) => Ok(ptr as *const c_void),
121-
None => Err(MissingExtensionFunctionError { name }),
119+
wglSwapIntervalEXT: transmute::<PROC, Option<WglSwapIntervalEXT>>(
120+
wglGetProcAddress(s!("wglSwapIntervalEXT")),
121+
),
122+
}
122123
}
123124
}
124125

125126
pub fn create_context_for_config(
126127
&self, dc: &OwnDeviceContext, config: &GlConfig,
127-
) -> windows_core::Result<WglContext> {
128+
) -> Result<WglContext, CreateContextError> {
129+
let Some(wglCreateContextAttribsARB) = self.wglCreateContextAttribsARB else {
130+
return Err(CreateContextError::Unavailable);
131+
};
128132
let profile_mask = match config.profile {
129133
Profile::Core => WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
130134
Profile::Compatibility => WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
@@ -138,17 +142,22 @@ impl WglExtra {
138142
0
139143
];
140144

141-
let ctx = unsafe {
142-
(self.wglCreateContextAttribsARB)(dc.as_raw(), null_mut(), ctx_attribs.as_ptr())
143-
};
145+
let ctx =
146+
unsafe { wglCreateContextAttribsARB(dc.as_raw(), null_mut(), ctx_attribs.as_ptr()) };
144147

145-
let ctx = NonNull::new(ctx).ok_or_else(Error::from_thread)?;
148+
let ctx =
149+
NonNull::new(ctx).ok_or_else(|| CreateContextError::Win32(Error::from_thread()))?;
146150

147151
Ok(WglContext { inner: ctx })
148152
}
149153

150154
pub fn set_vsync(&self, vsync: bool) -> windows_core::Result<()> {
151-
let result = unsafe { (self.wglSwapIntervalEXT)(vsync.into()) };
155+
let Some(wglSwapIntervalEXT) = self.wglSwapIntervalEXT else {
156+
warn!("Could not set vsync: wglSwapIntervalEXT is not available");
157+
return Ok(());
158+
};
159+
160+
let result = unsafe { wglSwapIntervalEXT(vsync.into()) };
152161
if result == 0 {
153162
return Err(Error::from_thread());
154163
}
@@ -158,11 +167,15 @@ impl WglExtra {
158167

159168
pub fn choose_pixel_format_from_attribs(
160169
&self, attribs: &PixelFormatAttribs, dc: &OwnDeviceContext,
161-
) -> windows_core::Result<Option<NonZeroI32>> {
170+
) -> Result<Option<NonZeroI32>, ChoosePixelFormatFromAttribsError> {
171+
let Some(wglChoosePixelFormatARB) = self.wglChoosePixelFormatARB else {
172+
return Err(ChoosePixelFormatFromAttribsError::Unavailable);
173+
};
174+
162175
let mut pixel_formats = [0];
163176
let mut num_formats = 0;
164177
let result = unsafe {
165-
(self.wglChoosePixelFormatARB)(
178+
wglChoosePixelFormatARB(
166179
dc.as_raw(),
167180
attribs.inner.as_ptr(),
168181
std::ptr::null(),
@@ -173,7 +186,7 @@ impl WglExtra {
173186
};
174187

175188
if result == 0 {
176-
return Err(Error::from_thread());
189+
return Err(ChoosePixelFormatFromAttribsError::Win32(Error::from_thread()));
177190
}
178191

179192
if num_formats == 0 {
@@ -184,6 +197,38 @@ impl WglExtra {
184197
}
185198
}
186199

200+
pub enum CreateContextError {
201+
Win32(Error),
202+
Unavailable,
203+
}
204+
205+
impl Display for CreateContextError {
206+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
207+
match self {
208+
CreateContextError::Win32(err) => Display::fmt(err, f),
209+
CreateContextError::Unavailable => {
210+
f.write_str("wglCreateContextAttribsARB is not available")
211+
}
212+
}
213+
}
214+
}
215+
216+
pub enum ChoosePixelFormatFromAttribsError {
217+
Win32(Error),
218+
Unavailable,
219+
}
220+
221+
impl Display for ChoosePixelFormatFromAttribsError {
222+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
223+
match self {
224+
ChoosePixelFormatFromAttribsError::Win32(e) => Display::fmt(e, f),
225+
ChoosePixelFormatFromAttribsError::Unavailable => {
226+
f.write_str("wglChoosePixelFormatARB is not available")
227+
}
228+
}
229+
}
230+
}
231+
187232
const WGL_DRAW_TO_WINDOW_ARB: i32 = 0x2001;
188233
const WGL_ACCELERATION_ARB: i32 = 0x2003;
189234
const WGL_SUPPORT_OPENGL_ARB: i32 = 0x2010;

0 commit comments

Comments
 (0)