#![allow(dead_code)] use crate::frontends::native::gl_backend::RenderTarget;
use glutin::context::PossiblyCurrentContext;
use glutin::prelude::*;
use glutin::surface::{Surface, SwapInterval, WindowSurface};
use winit::window::Window;
use std::num::NonZeroU32;
use std::sync::Arc;
pub struct WinitRenderTarget {
window: Arc<Window>,
surface: Surface<WindowSurface>,
gl_context: PossiblyCurrentContext,
}
impl WinitRenderTarget {
pub fn new(
window: Arc<Window>,
surface: Surface<WindowSurface>,
gl_context: PossiblyCurrentContext,
) -> Self {
Self {
window,
surface,
gl_context,
}
}
pub fn window(&self) -> &Window {
&self.window
}
pub fn set_swap_interval(&self, vsync: bool) -> Result<(), String> {
let interval = if vsync {
SwapInterval::Wait(NonZeroU32::MIN)
} else {
SwapInterval::DontWait
};
self.surface
.set_swap_interval(&self.gl_context, interval)
.map_err(|e| format!("failed to set swap interval: {e}"))
}
}
impl RenderTarget for WinitRenderTarget {
fn window_size(&self) -> (u32, u32) {
let size = self
.window
.inner_size()
.to_logical::<u32>(self.window.scale_factor());
(size.width, size.height)
}
fn drawable_size(&self) -> (u32, u32) {
let size = self.window.inner_size();
(size.width, size.height)
}
fn swap_buffers(&self) {
if let Err(e) = self.surface.swap_buffers(&self.gl_context) {
eprintln!("failed to swap GL buffers: {e}");
}
}
fn make_current(&self) -> Result<(), String> {
self.gl_context
.make_current(&self.surface)
.map_err(|e| format!("failed to make GL context current: {e}"))
}
fn set_fullscreen(&mut self, enabled: bool) -> Result<(), String> {
self.window
.set_fullscreen(enabled.then_some(winit::window::Fullscreen::Borderless(None)));
Ok(())
}
fn set_mouse_grab(&mut self, enabled: bool) -> Result<(), String> {
let mode = if enabled {
winit::window::CursorGrabMode::Confined
} else {
winit::window::CursorGrabMode::None
};
self.window.set_cursor_grab(mode).or_else(|e| {
if enabled {
Ok(())
} else {
Err(format!("failed to release cursor grab: {e}"))
}
})
}
fn notify_resize(&mut self, w: u32, h: u32) {
if let (Some(w), Some(h)) = (NonZeroU32::new(w), NonZeroU32::new(h)) {
self.surface.resize(&self.gl_context, w, h);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn _assert_render_target_impl(_: &dyn RenderTarget) {}
#[allow(dead_code)]
fn _type_check(rt: &WinitRenderTarget) {
_assert_render_target_impl(rt);
}
}