use crate::errors::{AleaticoError, AleaticoResult};
use log::debug;
use std::sync::Arc;
use wgpu::{Adapter, CurrentSurfaceTexture, PresentMode};
use winit::window::Window;
pub struct Surface {
pub(crate) inner: wgpu::Surface<'static>,
pub(crate) config: wgpu::SurfaceConfiguration,
pub(crate) is_configured: bool,
}
impl Surface {
pub fn new(
window: Arc<Window>,
raw_surface: wgpu::Surface<'static>,
adapter: &mut Adapter,
) -> AleaticoResult<Self> {
let size = window.inner_size();
let surface_caps = raw_surface.get_capabilities(adapter);
let surface_format = surface_caps
.formats
.iter()
.find(|f| f.is_srgb())
.copied()
.unwrap_or(surface_caps.formats[0]);
let config = wgpu::SurfaceConfiguration {
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
format: surface_format,
width: size.width,
height: size.height,
present_mode: PresentMode::AutoVsync,
alpha_mode: surface_caps.alpha_modes[0],
view_formats: vec![],
desired_maximum_frame_latency: 2,
};
Ok(Self {
inner: raw_surface,
config,
is_configured: false,
})
}
pub fn resize(&mut self, device: &wgpu::Device, width: u32, height: u32) {
debug!("can we pretend to leave and then we'll meet again when both our cars collide?");
if width > 0 && height > 0 {
self.config.width = width;
self.config.height = height;
self.inner.configure(&device, &self.config);
self.is_configured = true;
}
}
pub(crate) fn acquire_frame(
&mut self,
device: &wgpu::Device,
) -> AleaticoResult<Option<SurfaceFrame>> {
if !self.is_configured {
return Ok(None);
}
let output = match self.inner.get_current_texture() {
CurrentSurfaceTexture::Success(surface_texture) => surface_texture,
CurrentSurfaceTexture::Suboptimal(surface_texture) => {
drop(surface_texture);
self.inner.configure(&device, &self.config);
match self.inner.get_current_texture() {
CurrentSurfaceTexture::Success(surface_texture) => surface_texture,
CurrentSurfaceTexture::Suboptimal(surface_texture) => surface_texture,
_ => return Ok(None),
}
}
CurrentSurfaceTexture::Timeout
| CurrentSurfaceTexture::Occluded
| CurrentSurfaceTexture::Validation => {
return Ok(None);
}
CurrentSurfaceTexture::Outdated => {
self.inner.configure(&device, &self.config);
return Ok(None);
}
CurrentSurfaceTexture::Lost => {
return Err(AleaticoError::LostDevice);
}
};
let view = output
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
Ok(Some(SurfaceFrame { output, view }))
}
}
pub(crate) struct SurfaceFrame {
output: wgpu::SurfaceTexture,
view: wgpu::TextureView,
}
impl SurfaceFrame {
pub fn view(&self) -> &wgpu::TextureView {
&self.view
}
pub fn present(self) {
self.output.present();
}
}