Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Added `Buffer::pixel_rows()` for iterating over rows of the buffer data.
- Added `Buffer::pixels_iter()` for iterating over each pixel with its associated `x`/`y` coordinate.
- Added `Buffer::byte_stride()` for pixel buffers whose rows are aligned and may contain padding bytes at the end. Prefer to use the above helpers instead of accessing pixel data directly.
- Renamed `Surface::buffer_mut()` to `Surface::next_buffer()`.
- **Breaking:** Add `Pixel` struct, and use that for pixels instead of `u32`.
- **Breaking:** The pixel format is now target-dependent. Access `PixelFormat::default()` to see which format is used on the current platform.
- **Breaking:** Removed generic type parameters `D` and `W` from `Buffer<'_>` struct.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ name = "winit_multithread_android"
crate-type = ["cdylib"]

[[bench]]
name = "buffer_mut"
name = "buffer"
harness = false

[dev-dependencies]
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ To use Softbuffer, first create a window using `winit`, `sdl3`, or any other cra
[`raw_window_handle::HasWindowHandle`].

Next, you create a [`Context`] and [`Surface`] from that window, and can now call
[`Surface::buffer_mut()`] to get a [`Buffer`] that you can draw into. Once you're done drawing, call
[`Surface::next_buffer()`] to get a [`Buffer`] that you can draw into. Once you're done drawing, call
[`Buffer::present()`] to show the buffer on the window.

Note that Softbuffer only provides the `&mut [...]` buffer, it does not provide any rendering
Expand Down Expand Up @@ -117,7 +117,7 @@ fn main() {
)
.unwrap();

let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
for (x, y, pixel) in buffer.pixels_iter() {
let red = (x % 255) as u8;
let green = (y % 255) as u8;
Expand Down
14 changes: 7 additions & 7 deletions benches/buffer_mut.rs → benches/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
all(target_vendor = "apple", not(target_os = "macos")),
target_os = "redox"
)))]
fn buffer_mut(c: &mut criterion::Criterion) {
fn buffer(c: &mut criterion::Criterion) {
use criterion::black_box;
use softbuffer::{Context, Pixel, Surface};
use std::num::NonZeroU32;
Expand Down Expand Up @@ -34,30 +34,30 @@ fn buffer_mut(c: &mut criterion::Criterion) {
)
.unwrap();

c.bench_function("buffer_mut()", |b| {
c.bench_function("next_buffer()", |b| {
b.iter(|| {
black_box(surface.buffer_mut().unwrap());
black_box(surface.next_buffer().unwrap());
});
});

c.bench_function("pixels()", |b| {
let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
b.iter(|| {
let pixels: &mut [Pixel] = buffer.pixels();
black_box(pixels);
});
});

c.bench_function("fill pixels", |b| {
let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
b.iter(|| {
let buffer = black_box(&mut buffer);
buffer.pixels().fill(Pixel::default());
});
});

c.bench_function("render pixels_iter", |b| {
let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
b.iter(|| {
let buffer = black_box(&mut buffer);
for (x, y, pixel) in buffer.pixels_iter() {
Expand All @@ -78,7 +78,7 @@ fn buffer_mut(c: &mut criterion::Criterion) {
all(target_vendor = "apple", not(target_os = "macos")),
target_os = "redox"
)))]
criterion::criterion_group!(benches, buffer_mut);
criterion::criterion_group!(benches, buffer);

#[cfg(not(any(
target_family = "wasm",
Expand Down
2 changes: 1 addition & 1 deletion examples/animation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fn main() {

let elapsed = start.elapsed().as_secs_f64() % 1.0;

let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();

let size = (buffer.width().get(), buffer.height().get());
if size != *old_size {
Expand Down
2 changes: 1 addition & 1 deletion examples/drm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ mod imple {
tracing::info!("Drawing tick {tick}");

// Start drawing.
let mut buffer = surface.buffer_mut()?;
let mut buffer = surface.next_buffer()?;
draw_to_buffer(buffer.pixels(), tick);
buffer.present()?;

Expand Down
2 changes: 1 addition & 1 deletion examples/fruit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fn main() {
return;
};

let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
let stride = buffer.byte_stride().get() / 4;
for (x, y, pixel) in fruit.pixels() {
let pixel = Pixel::new_rgb(pixel.0[0], pixel.0[1], pixel.0[2]);
Expand Down
2 changes: 1 addition & 1 deletion examples/libxcb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ mod example {
NonZeroU32::new(height.into()).unwrap(),
)
.unwrap();
let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
buffer.pixels().fill(Pixel::new_rgb(0xff, 0, 0));
buffer.present().unwrap();
}
Expand Down
2 changes: 1 addition & 1 deletion examples/raytracing/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ fn main() {

game.update();

let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
game.draw(&mut buffer, window.scale_factor() as f32);
buffer.present().unwrap();
window.request_redraw();
Expand Down
2 changes: 1 addition & 1 deletion examples/rectangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ fn main() {
return;
};
// Draw something in the window
let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
redraw(&mut buffer, *flag);
buffer.present().unwrap();
}
Expand Down
2 changes: 1 addition & 1 deletion examples/winit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
return;
};

let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
for (x, y, pixel) in buffer.pixels_iter() {
let red = x % 255;
let green = y % 255;
Expand Down
2 changes: 1 addition & 1 deletion examples/winit_multithread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub mod ex {
tracing::info!("resizing...");
surface.resize(width, height).unwrap();

let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
for (x, y, pixel) in buffer.pixels_iter() {
let red = x % 255;
let green = y % 255;
Expand Down
2 changes: 1 addition & 1 deletion examples/winit_wrong_sized_buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ fn main() {
return;
};

let mut buffer = surface.buffer_mut().unwrap();
let mut buffer = surface.next_buffer().unwrap();
for (x, y, pixel) in buffer.pixels_iter() {
let red = x % 255;
let green = y % 255;
Expand Down
4 changes: 2 additions & 2 deletions src/backend_dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ macro_rules! make_dispatch {
}
}

fn buffer_mut(&mut self) -> Result<BufferDispatch<'_>, SoftBufferError> {
fn next_buffer(&mut self) -> Result<BufferDispatch<'_>, SoftBufferError> {
match self {
$(
$(#[$attr])*
Self::$name(inner) => Ok(BufferDispatch::$name(inner.buffer_mut()?)),
Self::$name(inner) => Ok(BufferDispatch::$name(inner.next_buffer()?)),
)*
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/backend_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ pub(crate) trait SurfaceInterface<D: HasDisplayHandle + ?Sized, W: HasWindowHand
fn window(&self) -> &W;
/// Resize the internal buffer to the given width and height.
fn resize(&mut self, width: NonZeroU32, height: NonZeroU32) -> Result<(), SoftBufferError>;
/// Get a mutable reference to the buffer.
fn buffer_mut(&mut self) -> Result<Self::Buffer<'_>, SoftBufferError>;
/// Get the next buffer to render into.
fn next_buffer(&mut self) -> Result<Self::Buffer<'_>, SoftBufferError>;
/// Fetch the buffer from the window.
fn fetch(&mut self) -> Result<Vec<Pixel>, SoftBufferError> {
Err(SoftBufferError::Unimplemented)
Expand Down
2 changes: 1 addition & 1 deletion src/backends/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Android
})
}

fn buffer_mut(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
fn next_buffer(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
let native_window_buffer = self.native_window.lock(None).map_err(|err| {
SoftBufferError::PlatformError(
Some("Failed to lock ANativeWindow".to_owned()),
Expand Down
2 changes: 1 addition & 1 deletion src/backends/cg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for CGImpl<
Ok(())
}

fn buffer_mut(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
fn next_buffer(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
let buffer_size = util::byte_stride(self.width as u32) as usize * self.height / 4;
Ok(BufferImpl {
buffer: util::PixelBuffer(vec![Pixel::default(); buffer_size]),
Expand Down
4 changes: 2 additions & 2 deletions src/backends/kms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,12 +252,12 @@ impl<D: HasDisplayHandle + ?Sized, W: HasWindowHandle> SurfaceInterface<D, W> fo
}
*/

fn buffer_mut(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
fn next_buffer(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
// Map the dumb buffer.
let set = self
.buffer
.as_mut()
.expect("Must set size of surface before calling `buffer_mut()`");
.expect("Must set size of surface before calling `next_buffer()`");

let size = set.size();

Expand Down
2 changes: 1 addition & 1 deletion src/backends/orbital.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Orbital
Ok(())
}

fn buffer_mut(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
fn next_buffer(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
let (window_width, window_height) = window_size(self.window_fd());
let pixels = if self.width as usize == window_width && self.height as usize == window_height
{
Expand Down
4 changes: 2 additions & 2 deletions src/backends/wayland/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,10 @@ impl<D: HasDisplayHandle + ?Sized, W: HasWindowHandle> SurfaceInterface<D, W>
Ok(())
}

fn buffer_mut(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
fn next_buffer(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
let (width, height) = self
.size
.expect("Must set size of surface before calling `buffer_mut()`");
.expect("Must set size of surface before calling `next_buffer()`");

if let Some((_front, back)) = &mut self.buffers {
// Block if back buffer not released yet
Expand Down
2 changes: 1 addition & 1 deletion src/backends/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for WebImpl
Ok(())
}

fn buffer_mut(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
fn next_buffer(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
Ok(BufferImpl {
canvas: &self.canvas,
buffer: &mut self.buffer,
Expand Down
4 changes: 2 additions & 2 deletions src/backends/win32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,11 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for Win32Im
Ok(())
}

fn buffer_mut(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
fn next_buffer(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
let buffer = self
.buffer
.as_mut()
.expect("Must set size of surface before calling `buffer_mut()`");
.expect("Must set size of surface before calling `next_buffer()`");

Ok(BufferImpl {
window: &self.window,
Expand Down
12 changes: 6 additions & 6 deletions src/backends/x11.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,13 +344,13 @@ impl<D: HasDisplayHandle + ?Sized, W: HasWindowHandle> SurfaceInterface<D, W> fo
Ok(())
}

fn buffer_mut(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
tracing::trace!("buffer_mut: window={:X}", self.window);
fn next_buffer(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
tracing::trace!("next_buffer: window={:X}", self.window);

// Finish waiting on the previous `shm::PutImage` request, if any.
self.buffer.finish_wait(self.display.connection())?;

// We can now safely call `buffer_mut` on the buffer.
// We can now safely call `next_buffer` on the buffer.
Ok(BufferImpl {
connection: self.display.connection(),
window: self.window,
Expand Down Expand Up @@ -433,8 +433,8 @@ impl BufferInterface for BufferImpl<'_> {

#[inline]
fn pixels_mut(&mut self) -> &mut [Pixel] {
// SAFETY: We called `finish_wait` on the buffer, so it is safe to call `buffer_mut`.
unsafe { self.buffer.buffer_mut() }
// SAFETY: We called `finish_wait` on the buffer.
unsafe { self.buffer.as_mut() }
}

fn age(&self) -> u8 {
Expand Down Expand Up @@ -569,7 +569,7 @@ impl Buffer {
///
/// `finish_wait()` must be called in between `shm::PutImage` requests and this function.
#[inline]
unsafe fn buffer_mut(&mut self) -> &mut [Pixel] {
unsafe fn as_mut(&mut self) -> &mut [Pixel] {
match self {
Buffer::Shm(ref mut shm) => unsafe { shm.as_mut() },
Buffer::Wire(wire) => wire,
Expand Down
14 changes: 10 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> Surface<D, W> {
self.surface_impl.window()
}

/// Set the size of the buffer that will be returned by [`Surface::buffer_mut`].
/// Set the size of the buffer that will be returned by [`Surface::next_buffer()`].
///
/// If the size of the buffer does not match the size of the window, the buffer is drawn
/// in the upper-left corner of the window. It is recommended in most production use cases
Expand Down Expand Up @@ -153,8 +153,8 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> Surface<D, W> {
/// - On DRM/KMS, there is no reliable and sound way to wait for the page flip to happen from within
/// `softbuffer`. Therefore it is the responsibility of the user to wait for the page flip before
/// sending another frame.
pub fn buffer_mut(&mut self) -> Result<Buffer<'_>, SoftBufferError> {
let mut buffer_impl = self.surface_impl.buffer_mut()?;
pub fn next_buffer(&mut self) -> Result<Buffer<'_>, SoftBufferError> {
let mut buffer_impl = self.surface_impl.next_buffer()?;

debug_assert_eq!(
buffer_impl.byte_stride().get() % 4,
Expand All @@ -176,6 +176,12 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> Surface<D, W> {
_marker: PhantomData,
})
}

/// Rename to [`Surface::next_buffer()`].
#[deprecated = "renamed to `next_buffer()`"]
pub fn buffer_mut(&mut self) -> Result<Buffer<'_>, SoftBufferError> {
self.next_buffer()
}
}

impl<D: HasDisplayHandle, W: HasWindowHandle> AsRef<W> for Surface<D, W> {
Expand Down Expand Up @@ -369,7 +375,7 @@ impl Buffer<'_> {
///
/// # let buffer: softbuffer::Buffer<'_> = todo!();
/// # #[cfg(false)]
/// let buffer = surface.buffer_mut();
/// let buffer = surface.next_buffer();
///
/// let width = buffer.width().get();
/// let height = buffer.height().get();
Expand Down