Owned pixel buffer for no-copy presentation

This is based on the API that will be used for no-copy presentation. But
wraps it in `set_buffer`.

This also fixes the Wayland buffer code to set `self.width` and
`self.height` on resize, and set the length of the shared memory file
when the buffer is created.

Co-authored-by: jtnunley <jtnunley01@gmail.com>
This commit is contained in:
Ian Douglas Scott 2023-04-06 00:30:59 -07:00 committed by GitHub
parent e5d546ff9e
commit a09e4cf679
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 1176 additions and 438 deletions

View file

@ -2,6 +2,7 @@ use instant::Instant;
#[cfg(not(target_arch = "wasm32"))]
use rayon::prelude::*;
use std::f64::consts::PI;
use std::num::NonZeroU32;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::WindowBuilder;
@ -47,8 +48,17 @@ fn main() {
frames = pre_render_frames(width as usize, height as usize);
};
let buffer = &frames[((elapsed * 60.0).round() as usize).clamp(0, 59)];
surface.set_buffer(buffer.as_slice(), width as u16, height as u16);
let frame = &frames[((elapsed * 60.0).round() as usize).clamp(0, 59)];
surface
.resize(
NonZeroU32::new(width).unwrap(),
NonZeroU32::new(height).unwrap(),
)
.unwrap();
let mut buffer = surface.buffer_mut().unwrap();
buffer.copy_from_slice(frame);
buffer.present().unwrap();
}
Event::MainEventsCleared => {
window.request_redraw();

View file

@ -1,4 +1,5 @@
use image::GenericImageView;
use std::num::NonZeroU32;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::WindowBuilder;
@ -6,16 +7,6 @@ use winit::window::WindowBuilder;
fn main() {
//see fruit.jpg.license for the license of fruit.jpg
let fruit = image::load_from_memory(include_bytes!("fruit.jpg")).unwrap();
let buffer = fruit
.pixels()
.map(|(_x, _y, pixel)| {
let red = pixel.0[0] as u32;
let green = pixel.0[1] as u32;
let blue = pixel.0[2] as u32;
blue | (green << 8) | (red << 16)
})
.collect::<Vec<_>>();
let event_loop = EventLoop::new();
let window = WindowBuilder::new()
@ -45,7 +36,25 @@ fn main() {
match event {
Event::RedrawRequested(window_id) if window_id == window.id() => {
surface.set_buffer(&buffer, fruit.width() as u16, fruit.height() as u16);
surface
.resize(
NonZeroU32::new(fruit.width()).unwrap(),
NonZeroU32::new(fruit.height()).unwrap(),
)
.unwrap();
let mut buffer = surface.buffer_mut().unwrap();
let width = fruit.width() as usize;
for (x, y, pixel) in fruit.pixels() {
let red = pixel.0[0] as u32;
let green = pixel.0[1] as u32;
let blue = pixel.0[2] as u32;
let color = blue | (green << 8) | (red << 16);
buffer[y as usize * width + x as usize] = color;
}
buffer.present().unwrap();
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,

View file

@ -3,6 +3,7 @@
#[cfg(all(feature = "x11", any(target_os = "linux", target_os = "freebsd")))]
mod example {
use raw_window_handle::{RawDisplayHandle, RawWindowHandle, XcbDisplayHandle, XcbWindowHandle};
use std::num::NonZeroU32;
use x11rb::{
connection::Connection,
protocol::{
@ -12,6 +13,8 @@ mod example {
xcb_ffi::XCBConnection,
};
const RED: u32 = 255 << 16;
pub(crate) fn run() {
// Create a new XCB connection
let (conn, screen) = XCBConnection::connect(None).expect("Failed to connect to X server");
@ -96,13 +99,15 @@ mod example {
match event {
Event::Expose(_) => {
// Draw a width x height red rectangle.
let red = 255 << 16;
let source = std::iter::repeat(red)
.take((width as usize * height as usize) as _)
.collect::<Vec<_>>();
// Draw the buffer.
surface.set_buffer(&source, width, height);
surface
.resize(
NonZeroU32::new(width.into()).unwrap(),
NonZeroU32::new(height.into()).unwrap(),
)
.unwrap();
let mut buffer = surface.buffer_mut().unwrap();
buffer.fill(RED);
buffer.present().unwrap();
}
Event::ConfigureNotify(configure_notify) => {
width = configure_notify.width;

View file

@ -1,3 +1,4 @@
use std::num::NonZeroU32;
use winit::event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::WindowBuilder;
@ -43,7 +44,6 @@ fn main() {
let context = unsafe { softbuffer::Context::new(&window) }.unwrap();
let mut surface = unsafe { softbuffer::Surface::new(&context, &window) }.unwrap();
let mut buffer = Vec::new();
let mut flag = false;
event_loop.run(move |event, _, control_flow| {
@ -54,19 +54,21 @@ fn main() {
// Grab the window's client area dimensions
let (width, height) = {
let size = window.inner_size();
(size.width as usize, size.height as usize)
(size.width, size.height)
};
// Resize the off-screen buffer if the window size has changed
if buffer.len() != width * height {
buffer.resize(width * height, 0);
}
// Resize surface if needed
surface
.resize(
NonZeroU32::new(width).unwrap(),
NonZeroU32::new(height).unwrap(),
)
.unwrap();
// Draw something in the offscreen buffer
redraw(&mut buffer, width, height, flag);
// Blit the offscreen buffer to the window's client area
surface.set_buffer(&buffer, width as u16, height as u16);
// Draw something in the window
let mut buffer = surface.buffer_mut().unwrap();
redraw(&mut buffer, width as usize, height as usize, flag);
buffer.present().unwrap();
}
Event::WindowEvent {

View file

@ -1,3 +1,4 @@
use std::num::NonZeroU32;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::WindowBuilder;
@ -32,21 +33,26 @@ fn main() {
let size = window.inner_size();
(size.width, size.height)
};
let buffer = (0..((width * height) as usize))
.map(|index| {
let y = index / (width as usize);
let x = index % (width as usize);
let red = x % 255;
let green = y % 255;
let blue = (x * y) % 255;
let color = blue | (green << 8) | (red << 16);
surface
.resize(
NonZeroU32::new(width).unwrap(),
NonZeroU32::new(height).unwrap(),
)
.unwrap();
color as u32
})
.collect::<Vec<_>>();
let mut buffer = surface.buffer_mut().unwrap();
for index in 0..(width * height) {
let y = index / width;
let x = index % width;
let red = x % 255;
let green = y % 255;
let blue = (x * y) % 255;
surface.set_buffer(&buffer, width as u16, height as u16);
buffer[index as usize] = blue | (green << 8) | (red << 16);
}
buffer.present().unwrap();
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,

View file

@ -1,3 +1,4 @@
use std::num::NonZeroU32;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::WindowBuilder;
@ -31,21 +32,25 @@ fn main() {
match event {
Event::RedrawRequested(window_id) if window_id == window.id() => {
let buffer = (0..(BUFFER_WIDTH * BUFFER_HEIGHT))
.map(|index| {
let y = index / BUFFER_WIDTH;
let x = index % BUFFER_WIDTH;
let red = x % 255;
let green = y % 255;
let blue = (x * y) % 255;
surface
.resize(
NonZeroU32::new(BUFFER_WIDTH as u32).unwrap(),
NonZeroU32::new(BUFFER_HEIGHT as u32).unwrap(),
)
.unwrap();
let mut buffer = surface.buffer_mut().unwrap();
for y in 0..BUFFER_HEIGHT {
for x in 0..BUFFER_WIDTH {
let red = x as u32 % 255;
let green = y as u32 % 255;
let blue = (x as u32 * y as u32) % 255;
let color = blue | (green << 8) | (red << 16);
color as u32
})
.collect::<Vec<_>>();
surface.set_buffer(&buffer, BUFFER_WIDTH as u16, BUFFER_HEIGHT as u16);
buffer[y * BUFFER_WIDTH + x] = color;
}
}
buffer.present().unwrap();
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,