use std::ops::{Deref, DerefMut};
use winit::{
event_loop::EventLoop,
window::{Window, WindowId},
};
#[derive(Debug, Clone, Copy)]
pub struct Config {
pub vsync: bool,
pub image_count: usize,
pub align: usize,
pub scanline_align: usize,
pub opaque: bool,
}
impl Config {
pub fn new() -> Self {
Self::default()
}
}
impl Default for Config {
fn default() -> Self {
Self {
vsync: true,
image_count: 2,
align: 128,
scanline_align: 128,
opaque: true,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Format {
Argb8888,
Xrgb8888,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ImageInfo {
pub extent: [u32; 2],
pub stride: usize,
pub format: Format,
}
impl Default for ImageInfo {
fn default() -> Self {
Self {
extent: [0, 0],
stride: 0,
format: Format::Argb8888,
}
}
}
#[derive(Debug)]
pub struct SwWindow {
surface: Option<Surface>,
window: Option<Window>,
}
impl SwWindow {
pub fn new(window: Window, context: &Context, config: &Config) -> Self {
Self {
surface: Some(unsafe { Surface::new(&window, context, config) }),
window: Some(window),
}
}
pub fn into_window(mut self) -> Window {
drop(self.surface.take());
self.window.take().unwrap()
}
pub unsafe fn split(mut self) -> (Surface, Window) {
(self.surface.take().unwrap(), self.window.take().unwrap())
}
pub fn window(&self) -> &Window {
self.window.as_ref().unwrap()
}
pub fn update_surface(&self, extent: [u32; 2], format: Format) {
self.surface
.as_ref()
.unwrap()
.update_surface(extent, format);
}
pub fn update_surface_to_fit(&self, format: Format) {
self.surface
.as_ref()
.unwrap()
.update_surface_to_fit(self.window.as_ref().unwrap(), format);
}
pub fn supported_formats(&self) -> impl Iterator<Item = Format> + '_ {
self.surface.as_ref().unwrap().supported_formats()
}
pub fn image_info(&self) -> ImageInfo {
self.surface.as_ref().unwrap().image_info()
}
pub fn num_images(&self) -> usize {
self.surface.as_ref().unwrap().num_images()
}
pub fn does_preserve_image(&self) -> bool {
self.surface.as_ref().unwrap().does_preserve_image()
}
pub fn poll_next_image(&self) -> Option<usize> {
self.surface.as_ref().unwrap().poll_next_image()
}
pub fn lock_image(&self, i: usize) -> impl Deref<Target = [u8]> + DerefMut + '_ {
self.surface.as_ref().unwrap().lock_image(i)
}
pub fn present_image(&self, i: usize) {
self.surface.as_ref().unwrap().present_image(i)
}
}
impl Drop for SwWindow {
fn drop(&mut self) {
drop(self.surface.take());
}
}
#[cfg(target_os = "windows")]
mod windows;
#[cfg(target_os = "windows")]
use self::windows::SurfaceImpl;
#[cfg(target_os = "windows")]
type ContextImpl = NullContextImpl;
#[cfg(any(target_os = "ios", target_os = "macos"))]
mod cglffi;
#[cfg(any(target_os = "ios", target_os = "macos"))]
mod objcutils;
#[cfg(target_os = "macos")]
mod cgl;
#[cfg(target_os = "macos")]
use self::cgl::SurfaceImpl;
#[cfg(target_os = "macos")]
type ContextImpl = NullContextImpl;
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
mod unix;
#[cfg(any(
target_os = "linux",
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd"
))]
use self::unix::{ContextImpl, SurfaceImpl};
mod align;
mod buffer;
#[allow(dead_code)]
pub struct ContextBuilder<'a, T: 'static> {
event_loop: &'a EventLoop<T>,
ready_cb: ReadyCb,
}
type ReadyCb = Box<dyn Fn(WindowId)>;
impl<'a, T: 'static> ContextBuilder<'a, T> {
pub fn new(event_loop: &'a EventLoop<T>) -> Self {
Self {
event_loop,
ready_cb: Box::new(|_| {}),
}
}
pub fn with_ready_cb(self, cb: impl Fn(WindowId) + 'static) -> Self {
if ContextImpl::TAKES_READY_CB {
Self {
ready_cb: Box::new(cb),
..self
}
} else {
self
}
}
pub fn build(self) -> Context {
Context {
inner: ContextImpl::new(self),
}
}
}
#[derive(Debug)]
pub struct Context {
inner: ContextImpl,
}
#[allow(dead_code)]
#[derive(Debug)]
struct NullContextImpl;
#[allow(dead_code)]
impl NullContextImpl {
const TAKES_READY_CB: bool = false;
fn new<T: 'static>(_: ContextBuilder<'_, T>) -> Self {
Self {}
}
}
#[derive(Debug)]
pub struct Surface {
inner: SurfaceImpl,
}
impl Surface {
pub unsafe fn new(window: &Window, context: &Context, config: &Config) -> Self {
Self {
inner: SurfaceImpl::new(window, &context.inner, config),
}
}
pub fn update_surface(&self, extent: [u32; 2], format: Format) {
self.inner.update_surface(extent, format);
}
pub fn update_surface_to_fit(&self, window: &Window, format: Format) {
let (size_w, size_h) = window.inner_size().into();
self.update_surface([size_w, size_h], format);
}
pub fn supported_formats(&self) -> impl Iterator<Item = Format> + '_ {
self.inner.supported_formats()
}
pub fn image_info(&self) -> ImageInfo {
self.inner.image_info()
}
pub fn num_images(&self) -> usize {
self.inner.num_images()
}
pub fn does_preserve_image(&self) -> bool {
self.inner.does_preserve_image()
}
pub fn poll_next_image(&self) -> Option<usize> {
self.inner.poll_next_image()
}
pub fn lock_image(&self, i: usize) -> impl Deref<Target = [u8]> + DerefMut + '_ {
self.inner.lock_image(i)
}
pub fn present_image(&self, i: usize) {
self.inner.present_image(i)
}
}