Fix invalid texture sizes (#250)
- Makes methods fallible when they create textures. - Correctly handle window resize in fltk example. - TODO: tests - Closes #240
This commit is contained in:
parent
b4fc48c740
commit
6f4fa6c967
|
@ -45,11 +45,8 @@ fn main() -> Result<(), Error> {
|
|||
// The one and only event that winit_input_helper doesn't have for us...
|
||||
if let Event::RedrawRequested(_) = event {
|
||||
life.draw(pixels.get_frame_mut());
|
||||
if pixels
|
||||
.render()
|
||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = pixels.render() {
|
||||
error!("pixels.render() failed: {}", err);
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
@ -98,17 +95,17 @@ fn main() -> Result<(), Error> {
|
|||
.unwrap_or_default();
|
||||
|
||||
if input.mouse_pressed(0) {
|
||||
debug!("Mouse click at {:?}", mouse_cell);
|
||||
debug!("Mouse click at {mouse_cell:?}");
|
||||
draw_state = Some(life.toggle(mouse_cell.0, mouse_cell.1));
|
||||
} else if let Some(draw_alive) = draw_state {
|
||||
let release = input.mouse_released(0);
|
||||
let held = input.mouse_held(0);
|
||||
debug!("Draw at {:?} => {:?}", mouse_prev_cell, mouse_cell);
|
||||
debug!("Mouse held {:?}, release {:?}", held, release);
|
||||
debug!("Draw at {mouse_prev_cell:?} => {mouse_cell:?}");
|
||||
debug!("Mouse held {held:?}, release {release:?}");
|
||||
// If they either released (finishing the drawing) or are still
|
||||
// in the middle of drawing, keep going.
|
||||
if release || held {
|
||||
debug!("Draw line of {:?}", draw_alive);
|
||||
debug!("Draw line of {draw_alive:?}");
|
||||
life.set_line(
|
||||
mouse_prev_cell.0,
|
||||
mouse_prev_cell.1,
|
||||
|
@ -125,7 +122,11 @@ fn main() -> Result<(), Error> {
|
|||
}
|
||||
// Resize the window
|
||||
if let Some(size) = input.window_resized() {
|
||||
pixels.resize_surface(size.width, size.height);
|
||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if !paused || input.key_pressed_os(VirtualKeyCode::Space) {
|
||||
life.update();
|
||||
|
|
|
@ -45,7 +45,7 @@ fn main() -> Result<(), Error> {
|
|||
};
|
||||
let mut world = World::new();
|
||||
let mut time = 0.0;
|
||||
let mut noise_renderer = NoiseRenderer::new(&pixels, window_size.width, window_size.height);
|
||||
let mut noise_renderer = NoiseRenderer::new(&pixels, window_size.width, window_size.height)?;
|
||||
|
||||
event_loop.run(move |event, _, control_flow| {
|
||||
// Draw the current frame
|
||||
|
@ -64,10 +64,8 @@ fn main() -> Result<(), Error> {
|
|||
Ok(())
|
||||
});
|
||||
|
||||
if render_result
|
||||
.map_err(|e| error!("pixels.render_with() failed: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = render_result {
|
||||
error!("pixels.render_with() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
@ -83,8 +81,16 @@ fn main() -> Result<(), Error> {
|
|||
|
||||
// Resize the window
|
||||
if let Some(size) = input.window_resized() {
|
||||
pixels.resize_surface(size.width, size.height);
|
||||
noise_renderer.resize(&pixels, size.width, size.height);
|
||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
if let Err(err) = noise_renderer.resize(&pixels, size.width, size.height) {
|
||||
error!("noise_renderer.resize() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update internal state and request a redraw
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
use pixels::wgpu::{self, util::DeviceExt};
|
||||
use pixels::{
|
||||
check_texture_size,
|
||||
wgpu::{self, util::DeviceExt},
|
||||
TextureError,
|
||||
};
|
||||
|
||||
pub(crate) struct NoiseRenderer {
|
||||
texture_view: wgpu::TextureView,
|
||||
|
@ -11,14 +15,18 @@ pub(crate) struct NoiseRenderer {
|
|||
}
|
||||
|
||||
impl NoiseRenderer {
|
||||
pub(crate) fn new(pixels: &pixels::Pixels, width: u32, height: u32) -> Self {
|
||||
pub(crate) fn new(
|
||||
pixels: &pixels::Pixels,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Result<Self, TextureError> {
|
||||
let device = pixels.device();
|
||||
let shader = wgpu::include_wgsl!("../shaders/noise.wgsl");
|
||||
let module = device.create_shader_module(shader);
|
||||
|
||||
// Create a texture view that will be used as input
|
||||
// This will be used as the render target for the default scaling renderer
|
||||
let texture_view = create_texture_view(pixels, width, height);
|
||||
let texture_view = create_texture_view(pixels, width, height)?;
|
||||
|
||||
// Create a texture sampler with nearest neighbor
|
||||
let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
|
@ -139,7 +147,7 @@ impl NoiseRenderer {
|
|||
multiview: None,
|
||||
});
|
||||
|
||||
Self {
|
||||
Ok(Self {
|
||||
texture_view,
|
||||
sampler,
|
||||
bind_group_layout,
|
||||
|
@ -147,19 +155,20 @@ impl NoiseRenderer {
|
|||
render_pipeline,
|
||||
time_buffer,
|
||||
vertex_buffer,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn get_texture_view(&self) -> &wgpu::TextureView {
|
||||
&self.texture_view
|
||||
}
|
||||
|
||||
pub(crate) fn resize(&mut self, pixels: &pixels::Pixels, width: u32, height: u32) {
|
||||
if width == 0 || height == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
self.texture_view = create_texture_view(pixels, width, height);
|
||||
pub(crate) fn resize(
|
||||
&mut self,
|
||||
pixels: &pixels::Pixels,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Result<(), TextureError> {
|
||||
self.texture_view = create_texture_view(pixels, width, height)?;
|
||||
self.bind_group = create_bind_group(
|
||||
pixels.device(),
|
||||
&self.bind_group_layout,
|
||||
|
@ -167,6 +176,8 @@ impl NoiseRenderer {
|
|||
&self.sampler,
|
||||
&self.time_buffer,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn update(&self, queue: &wgpu::Queue, time: f32) {
|
||||
|
@ -199,8 +210,13 @@ impl NoiseRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
fn create_texture_view(pixels: &pixels::Pixels, width: u32, height: u32) -> wgpu::TextureView {
|
||||
fn create_texture_view(
|
||||
pixels: &pixels::Pixels,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Result<wgpu::TextureView, TextureError> {
|
||||
let device = pixels.device();
|
||||
check_texture_size(device, width, height)?;
|
||||
let texture_descriptor = wgpu::TextureDescriptor {
|
||||
label: None,
|
||||
size: pixels::wgpu::Extent3d {
|
||||
|
@ -215,9 +231,9 @@ fn create_texture_view(pixels: &pixels::Pixels, width: u32, height: u32) -> wgpu
|
|||
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::RENDER_ATTACHMENT,
|
||||
};
|
||||
|
||||
device
|
||||
Ok(device
|
||||
.create_texture(&texture_descriptor)
|
||||
.create_view(&wgpu::TextureViewDescriptor::default())
|
||||
.create_view(&wgpu::TextureViewDescriptor::default()))
|
||||
}
|
||||
|
||||
fn create_bind_group(
|
||||
|
|
|
@ -76,10 +76,8 @@ fn main() -> Result<(), Error> {
|
|||
});
|
||||
|
||||
// Basic error handling
|
||||
if render_result
|
||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = render_result {
|
||||
error!("pixels.render() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
@ -103,12 +101,20 @@ fn main() -> Result<(), Error> {
|
|||
if let Some(size) = input.window_resized() {
|
||||
if size.width > 0 && size.height > 0 {
|
||||
// Resize the surface texture
|
||||
pixels.resize_surface(size.width, size.height);
|
||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
||||
// Resize the world
|
||||
let LogicalSize { width, height } = size.to_logical(scale_factor);
|
||||
world.resize(width, height);
|
||||
pixels.resize_buffer(width, height);
|
||||
if let Err(err) = pixels.resize_buffer(width, height) {
|
||||
error!("pixels.resize_buffer() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,8 +140,8 @@ fn main() -> Result<(), Error> {
|
|||
move |g| {
|
||||
// Drawing
|
||||
g.game.world.draw(g.game.pixels.get_frame_mut());
|
||||
if let Err(e) = g.game.pixels.render() {
|
||||
error!("pixels.render() failed: {}", e);
|
||||
if let Err(err) = g.game.pixels.render() {
|
||||
error!("pixels.render() failed: {err}");
|
||||
g.exit();
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,10 @@ fn main() -> Result<(), Error> {
|
|||
|
||||
// Resize the window
|
||||
if let Some(size) = g.game.input.window_resized() {
|
||||
g.game.pixels.resize_surface(size.width, size.height);
|
||||
if let Err(err) = g.game.pixels.resize_surface(size.width, size.height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
g.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -71,7 +71,11 @@ fn main() -> Result<(), Error> {
|
|||
|
||||
// Resize the window
|
||||
if let Some(size) = input.window_resized() {
|
||||
pixels.resize_surface(size.width, size.height);
|
||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
framework.resize(size.width, size.height);
|
||||
}
|
||||
|
||||
|
@ -105,10 +109,8 @@ fn main() -> Result<(), Error> {
|
|||
});
|
||||
|
||||
// Basic error handling
|
||||
if render_result
|
||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = render_result {
|
||||
error!("pixels.render() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
#![forbid(unsafe_code)]
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
use fltk::{app, enums::Event, prelude::*, window::Window};
|
||||
use fltk::{app, prelude::*, window::Window};
|
||||
use log::error;
|
||||
use pixels::{Error, Pixels, SurfaceTexture};
|
||||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
const WIDTH: u32 = 600;
|
||||
const HEIGHT: u32 = 400;
|
||||
|
@ -26,6 +27,7 @@ fn main() -> Result<(), Error> {
|
|||
let mut win = Window::default()
|
||||
.with_size(WIDTH as i32, HEIGHT as i32)
|
||||
.with_label("Hello Pixels");
|
||||
win.make_resizable(true);
|
||||
win.end();
|
||||
win.show();
|
||||
|
||||
|
@ -33,29 +35,39 @@ fn main() -> Result<(), Error> {
|
|||
let pixel_width = win.pixel_w() as u32;
|
||||
let pixel_height = win.pixel_h() as u32;
|
||||
let surface_texture = SurfaceTexture::new(pixel_width, pixel_height, &win);
|
||||
|
||||
Pixels::new(WIDTH, HEIGHT, surface_texture)?
|
||||
};
|
||||
|
||||
let mut world = World::new();
|
||||
|
||||
while app.wait() {
|
||||
// Handle window events
|
||||
if app::event() == Event::Resize {
|
||||
let pixel_width = win.pixel_w() as u32;
|
||||
let pixel_height = win.pixel_h() as u32;
|
||||
pixels.resize_surface(pixel_width, pixel_height);
|
||||
}
|
||||
// Handle resize events
|
||||
let surface_size = Rc::new(RefCell::new(None));
|
||||
let surface_resize = surface_size.clone();
|
||||
win.resize_callback(move |win, _x, _y, width, height| {
|
||||
let scale_factor = win.pixels_per_unit();
|
||||
let width = (width as f32 * scale_factor) as u32;
|
||||
let height = (height as f32 * scale_factor) as u32;
|
||||
|
||||
surface_resize.borrow_mut().replace((width, height));
|
||||
});
|
||||
|
||||
while app.wait() {
|
||||
// Update internal state
|
||||
world.update();
|
||||
|
||||
// Resize the window
|
||||
if let Some((width, height)) = surface_size.borrow_mut().take() {
|
||||
if let Err(err) = pixels.resize_surface(width, height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
app.quit();
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the current frame
|
||||
world.draw(pixels.get_frame_mut());
|
||||
if pixels
|
||||
.render()
|
||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = pixels.render() {
|
||||
error!("pixels.render() failed: {err}");
|
||||
app.quit();
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,10 @@ fn main() -> Result<(), Error> {
|
|||
|
||||
// Resize the window
|
||||
WindowEvent::Resized(size) => {
|
||||
pixels.resize_surface(size.width, size.height);
|
||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
|
@ -82,11 +85,8 @@ fn main() -> Result<(), Error> {
|
|||
// Draw the current frame
|
||||
Event::RedrawRequested(_) => {
|
||||
world.draw(pixels.get_frame_mut());
|
||||
if pixels
|
||||
.render()
|
||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = pixels.render() {
|
||||
error!("pixels.render() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -111,11 +111,8 @@ async fn run() {
|
|||
// Draw the current frame
|
||||
if let Event::RedrawRequested(_) = event {
|
||||
world.draw(pixels.get_frame_mut());
|
||||
if pixels
|
||||
.render()
|
||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = pixels.render() {
|
||||
error!("pixels.render() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
@ -131,7 +128,11 @@ async fn run() {
|
|||
|
||||
// Resize the window
|
||||
if let Some(size) = input.window_resized() {
|
||||
pixels.resize_surface(size.width, size.height);
|
||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update internal state and request a redraw
|
||||
|
|
|
@ -46,11 +46,8 @@ fn main() -> Result<(), Error> {
|
|||
// Draw the current frame
|
||||
if let Event::RedrawRequested(_) = event {
|
||||
world.draw(pixels.get_frame_mut());
|
||||
if pixels
|
||||
.render()
|
||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = pixels.render() {
|
||||
error!("pixels.render() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
@ -66,7 +63,11 @@ fn main() -> Result<(), Error> {
|
|||
|
||||
// Resize the window
|
||||
if let Some(size) = input.window_resized() {
|
||||
pixels.resize_surface(size.width, size.height);
|
||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update internal state and request a redraw
|
||||
|
|
|
@ -56,11 +56,8 @@ fn main() -> Result<(), Error> {
|
|||
dst[3] = (src >> 24) as u8;
|
||||
}
|
||||
|
||||
if pixels
|
||||
.render()
|
||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = pixels.render() {
|
||||
error!("pixels.render() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
@ -76,7 +73,11 @@ fn main() -> Result<(), Error> {
|
|||
|
||||
// Resize the window
|
||||
if let Some(size) = input.window_resized() {
|
||||
pixels.resize_surface(size.width, size.height);
|
||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update internal state and request a redraw
|
||||
|
|
|
@ -44,11 +44,8 @@ fn main() -> Result<(), Error> {
|
|||
// Draw the current frame
|
||||
if let Event::RedrawRequested(_) = event {
|
||||
pixels.get_frame_mut().copy_from_slice(drawing.data());
|
||||
if pixels
|
||||
.render()
|
||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
||||
.is_err()
|
||||
{
|
||||
if let Err(err) = pixels.render() {
|
||||
error!("pixels.render() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
|
@ -64,7 +61,11 @@ fn main() -> Result<(), Error> {
|
|||
|
||||
// Resize the window
|
||||
if let Some(size) = input.window_resized() {
|
||||
pixels.resize_surface(size.width, size.height);
|
||||
if let Err(err) = pixels.resize_surface(size.width, size.height) {
|
||||
error!("pixels.resize_surface() failed: {err}");
|
||||
*control_flow = ControlFlow::Exit;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Update internal state and request a redraw
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use crate::renderers::{ScalingMatrix, ScalingRenderer};
|
||||
use crate::SurfaceSize;
|
||||
use crate::{Error, Pixels, PixelsContext, SurfaceTexture};
|
||||
use crate::{Error, Pixels, PixelsContext, SurfaceSize, SurfaceTexture, TextureError};
|
||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||
|
||||
/// A builder to help create customized pixel buffers.
|
||||
|
@ -321,7 +320,7 @@ impl<'req, 'dev, 'win, W: HasRawWindowHandle + HasRawDisplayHandle>
|
|||
render_texture_format,
|
||||
clear_color,
|
||||
blend_state,
|
||||
);
|
||||
)?;
|
||||
|
||||
// Create the pixel buffer
|
||||
let mut pixels = Vec::with_capacity(pixels_buffer_size);
|
||||
|
@ -397,6 +396,28 @@ impl<'req, 'dev, 'win, W: HasRawWindowHandle + HasRawDisplayHandle>
|
|||
}
|
||||
}
|
||||
|
||||
/// Compare the given size to the limits defined by `device`.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - [`TextureError::TextureWidth`] when `width` is 0 or greater than GPU texture limits.
|
||||
/// - [`TextureError::TextureHeight`] when `height` is 0 or greater than GPU texture limits.
|
||||
pub fn check_texture_size(
|
||||
device: &wgpu::Device,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Result<(), TextureError> {
|
||||
let limits = device.limits();
|
||||
if width == 0 || width > limits.max_texture_dimension_2d {
|
||||
return Err(TextureError::TextureWidth(width));
|
||||
}
|
||||
if height == 0 || height > limits.max_texture_dimension_2d {
|
||||
return Err(TextureError::TextureHeight(height));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn create_backing_texture(
|
||||
device: &wgpu::Device,
|
||||
|
@ -407,13 +428,18 @@ pub(crate) fn create_backing_texture(
|
|||
render_texture_format: wgpu::TextureFormat,
|
||||
clear_color: wgpu::Color,
|
||||
blend_state: wgpu::BlendState,
|
||||
) -> (
|
||||
ultraviolet::Mat4,
|
||||
wgpu::Extent3d,
|
||||
wgpu::Texture,
|
||||
ScalingRenderer,
|
||||
usize,
|
||||
) {
|
||||
) -> Result<
|
||||
(
|
||||
ultraviolet::Mat4,
|
||||
wgpu::Extent3d,
|
||||
wgpu::Texture,
|
||||
ScalingRenderer,
|
||||
usize,
|
||||
),
|
||||
TextureError,
|
||||
> {
|
||||
check_texture_size(device, width, height)?;
|
||||
|
||||
let scaling_matrix_inverse = ScalingMatrix::new(
|
||||
(width as f32, height as f32),
|
||||
(surface_size.width as f32, surface_size.height as f32),
|
||||
|
@ -451,13 +477,13 @@ pub(crate) fn create_backing_texture(
|
|||
let texture_format_size = get_texture_format_size(backing_texture_format);
|
||||
let pixels_buffer_size = ((width * height) as f32 * texture_format_size) as usize;
|
||||
|
||||
(
|
||||
Ok((
|
||||
scaling_matrix_inverse,
|
||||
texture_extent,
|
||||
texture,
|
||||
scaling_renderer,
|
||||
pixels_buffer_size,
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
|
|
45
src/lib.rs
45
src/lib.rs
|
@ -31,7 +31,7 @@
|
|||
|
||||
#![deny(clippy::all)]
|
||||
|
||||
pub use crate::builder::PixelsBuilder;
|
||||
pub use crate::builder::{check_texture_size, PixelsBuilder};
|
||||
pub use crate::renderers::ScalingRenderer;
|
||||
pub use raw_window_handle;
|
||||
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
||||
|
@ -111,6 +111,7 @@ pub struct Pixels {
|
|||
|
||||
/// All the ways in which creating a pixel buffer can fail.
|
||||
#[derive(Error, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum Error {
|
||||
/// No suitable [`wgpu::Adapter`] found
|
||||
#[error("No suitable `wgpu::Adapter` found.")]
|
||||
|
@ -121,6 +122,9 @@ pub enum Error {
|
|||
/// Equivalent to [`wgpu::SurfaceError`]
|
||||
#[error("The GPU failed to acquire a surface frame.")]
|
||||
Surface(wgpu::SurfaceError),
|
||||
/// Equivalent to [`TextureError`]
|
||||
#[error("Texture creation failed: {0}")]
|
||||
InvalidTexture(#[from] TextureError),
|
||||
/// User-defined error from custom render function
|
||||
#[error("User-defined error.")]
|
||||
UserDefined(#[from] DynError),
|
||||
|
@ -128,6 +132,18 @@ pub enum Error {
|
|||
|
||||
type DynError = Box<dyn std::error::Error + Send + Sync + 'static>;
|
||||
|
||||
/// All the ways in which creating a texture can fail.
|
||||
#[derive(Error, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub enum TextureError {
|
||||
/// Unable to create a backing texture; Width is either 0 or greater than GPU limits
|
||||
#[error("Texture width is invalid: {0}")]
|
||||
TextureWidth(u32),
|
||||
/// Unable to create a backing texture; Height is either 0 or greater than GPU limits
|
||||
#[error("Texture height is invalid: {0}")]
|
||||
TextureHeight(u32),
|
||||
}
|
||||
|
||||
impl<'win, W: HasRawWindowHandle + HasRawDisplayHandle> SurfaceTexture<'win, W> {
|
||||
/// Create a logical texture for a window surface.
|
||||
///
|
||||
|
@ -268,13 +284,11 @@ impl Pixels {
|
|||
/// Call this method to change the virtual screen resolution. E.g. when you want your pixel
|
||||
/// buffer to be resized from `640x480` to `800x600`.
|
||||
///
|
||||
/// # Panics
|
||||
/// # Errors
|
||||
///
|
||||
/// Panics when `width` or `height` are 0.
|
||||
pub fn resize_buffer(&mut self, width: u32, height: u32) {
|
||||
assert!(width > 0);
|
||||
assert!(height > 0);
|
||||
|
||||
/// - [`TextureError::TextureWidth`] when `width` is 0 or greater than GPU texture limits.
|
||||
/// - [`TextureError::TextureHeight`] when `height` is 0 or greater than GPU texture limits.
|
||||
pub fn resize_buffer(&mut self, width: u32, height: u32) -> Result<(), TextureError> {
|
||||
// Recreate the backing texture
|
||||
let (scaling_matrix_inverse, texture_extent, texture, scaling_renderer, pixels_buffer_size) =
|
||||
builder::create_backing_texture(
|
||||
|
@ -288,7 +302,7 @@ impl Pixels {
|
|||
self.render_texture_format,
|
||||
self.context.scaling_renderer.clear_color,
|
||||
self.blend_state,
|
||||
);
|
||||
)?;
|
||||
|
||||
self.scaling_matrix_inverse = scaling_matrix_inverse;
|
||||
self.context.texture_extent = texture_extent;
|
||||
|
@ -298,6 +312,8 @@ impl Pixels {
|
|||
// Resize the pixel buffer
|
||||
self.pixels
|
||||
.resize_with(pixels_buffer_size, Default::default);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resize the surface upon which the pixel buffer texture is rendered.
|
||||
|
@ -311,10 +327,13 @@ impl Pixels {
|
|||
///
|
||||
/// Call this method in response to a resize event from your window manager. The size expected
|
||||
/// is in physical pixel units. Does nothing when `width` or `height` are 0.
|
||||
pub fn resize_surface(&mut self, width: u32, height: u32) {
|
||||
if width == 0 || height == 0 {
|
||||
return;
|
||||
}
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// - [`TextureError::TextureWidth`] when `width` is 0 or greater than GPU texture limits.
|
||||
/// - [`TextureError::TextureHeight`] when `height` is 0 or greater than GPU texture limits.
|
||||
pub fn resize_surface(&mut self, width: u32, height: u32) -> Result<(), TextureError> {
|
||||
check_texture_size(&self.context.device, width, height)?;
|
||||
|
||||
// Update SurfaceTexture dimensions
|
||||
self.surface_size.width = width;
|
||||
|
@ -338,6 +357,8 @@ impl Pixels {
|
|||
self.context
|
||||
.scaling_renderer
|
||||
.resize(&self.context.queue, width, height);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Draw this pixel buffer to the configured [`SurfaceTexture`].
|
||||
|
|
Loading…
Reference in a new issue