Skip to content

Commit 365e200

Browse files
committed
Add Pixel struct
This is much more intuitive to use than manually bit-packing into a u32. The format is RGBX on WASM and BGRX elsewhere. This should allow avoiding needless copying on WASM.
1 parent a9bae73 commit 365e200

25 files changed

+346
-164
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Unreleased
22

3+
- **Breaking:** Add `Pixel` struct, and use that for pixels instead of `u32`.
4+
35
- Update to `objc2` 0.6.0.
46
- Bump MSRV to Rust 1.71.
57
- Make `Context` cloneable.

Cargo.toml

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ harness = false
1818

1919
[features]
2020
default = ["kms", "x11", "x11-dlopen", "wayland", "wayland-dlopen"]
21-
kms = ["bytemuck", "drm", "rustix"]
21+
kms = ["drm", "rustix"]
2222
wayland = [
2323
"wayland-backend",
2424
"wayland-client",
@@ -28,14 +28,7 @@ wayland = [
2828
"fastrand",
2929
]
3030
wayland-dlopen = ["wayland-sys/dlopen"]
31-
x11 = [
32-
"as-raw-xcb-connection",
33-
"bytemuck",
34-
"fastrand",
35-
"rustix",
36-
"tiny-xlib",
37-
"x11rb",
38-
]
31+
x11 = ["as-raw-xcb-connection", "fastrand", "rustix", "tiny-xlib", "x11rb"]
3932
x11-dlopen = ["tiny-xlib/dlopen", "x11rb/dl-libxcb"]
4033

4134
[dependencies]
@@ -45,12 +38,10 @@ raw_window_handle = { package = "raw-window-handle", version = "0.6", features =
4538
tracing = { version = "0.1.41", default-features = false }
4639

4740
[target.'cfg(target_os = "android")'.dependencies]
48-
bytemuck = "1.12.3"
4941
ndk = "0.9.0"
5042

5143
[target.'cfg(all(unix, not(any(target_vendor = "apple", target_os = "android", target_os = "redox"))))'.dependencies]
5244
as-raw-xcb-connection = { version = "1.0.0", optional = true }
53-
bytemuck = { version = "1.12.3", optional = true }
5445
drm = { version = "0.14.1", default-features = false, optional = true }
5546
fastrand = { version = "2.0.0", optional = true }
5647
memmap2 = { version = "0.9.0", optional = true }

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ fn main() {
113113
for index in 0..(buffer.width().get() * buffer.height().get()) {
114114
let y = index / buffer.width().get();
115115
let x = index % buffer.width().get();
116-
let red = x % 255;
117-
let green = y % 255;
118-
let blue = (x * y) % 255;
116+
let red = (x % 255) as u8;
117+
let green = (y % 255) as u8;
118+
let blue = ((x * y) % 255) as u8;
119119
120-
buffer[index as usize] = blue | (green << 8) | (red << 16);
120+
buffer[index as usize] = softbuffer::Pixel::new_rgb(red, green, blue);
121121
}
122122
123123
buffer.present().unwrap();

benches/buffer_mut.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ fn buffer_mut(c: &mut Criterion) {
1212
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
1313
{
1414
use criterion::black_box;
15-
use softbuffer::{Context, Surface};
15+
use softbuffer::{Context, Pixel, Surface};
1616
use std::num::NonZeroU32;
1717
use winit::event_loop::ControlFlow;
1818
use winit::platform::run_on_demand::EventLoopExtRunOnDemand;
@@ -51,7 +51,7 @@ fn buffer_mut(c: &mut Criterion) {
5151
let mut buffer = surface.buffer_mut().unwrap();
5252
b.iter(|| {
5353
for _ in 0..500 {
54-
let x: &mut [u32] = &mut buffer;
54+
let x: &mut [Pixel] = &mut buffer;
5555
black_box(x);
5656
}
5757
});

examples/animation.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#[cfg(not(target_arch = "wasm32"))]
22
use rayon::prelude::*;
3+
use softbuffer::Pixel;
34
use std::f64::consts::PI;
45
use std::num::NonZeroU32;
56
use web_time::Instant;
@@ -94,7 +95,7 @@ fn main() {
9495
winit_app::run_app(event_loop, app);
9596
}
9697

97-
fn pre_render_frames(width: u32, height: u32) -> Vec<Vec<u32>> {
98+
fn pre_render_frames(width: u32, height: u32) -> Vec<Vec<Pixel>> {
9899
let render = |frame_id| {
99100
let elapsed = ((frame_id as f64) / (60.0)) * 2.0 * PI;
100101

@@ -103,14 +104,11 @@ fn pre_render_frames(width: u32, height: u32) -> Vec<Vec<u32>> {
103104
.map(|(x, y)| {
104105
let y = (y as f64) / (height as f64);
105106
let x = (x as f64) / (width as f64);
106-
let red =
107-
((((y + elapsed).sin() * 0.5 + 0.5) * 255.0).round() as u32).clamp(0, 255);
108-
let green =
109-
((((x + elapsed).sin() * 0.5 + 0.5) * 255.0).round() as u32).clamp(0, 255);
110-
let blue =
111-
((((y - elapsed).cos() * 0.5 + 0.5) * 255.0).round() as u32).clamp(0, 255);
112-
113-
blue | (green << 8) | (red << 16)
107+
let r = ((((y + elapsed).sin() * 0.5 + 0.5) * 255.0).round() as u32).clamp(0, 255);
108+
let g = ((((x + elapsed).sin() * 0.5 + 0.5) * 255.0).round() as u32).clamp(0, 255);
109+
let b = ((((y - elapsed).cos() * 0.5 + 0.5) * 255.0).round() as u32).clamp(0, 255);
110+
111+
Pixel::new_rgb(r as u8, g as u8, b as u8)
114112
})
115113
.collect::<Vec<_>>()
116114
};

examples/drm.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod imple {
66
use drm::Device;
77

88
use raw_window_handle::{DisplayHandle, DrmDisplayHandle, DrmWindowHandle, WindowHandle};
9-
use softbuffer::{Context, Surface};
9+
use softbuffer::{Context, Pixel, Surface};
1010

1111
use std::num::NonZeroU32;
1212
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd};
@@ -150,16 +150,15 @@ mod imple {
150150
Ok(())
151151
}
152152

153-
fn draw_to_buffer(buf: &mut [u32], tick: usize) {
153+
fn draw_to_buffer(buf: &mut [Pixel], tick: usize) {
154154
let scale = colorous::SINEBOW;
155155
let mut i = (tick as f64) / 20.0;
156156
while i > 1.0 {
157157
i -= 1.0;
158158
}
159159

160160
let color = scale.eval_continuous(i);
161-
let pixel = ((color.r as u32) << 16) | ((color.g as u32) << 8) | (color.b as u32);
162-
buf.fill(pixel);
161+
buf.fill(Pixel::new_rgb(color.r, color.g, color.b));
163162
}
164163

165164
struct Card(std::fs::File);

examples/fruit.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use image::GenericImageView;
2+
use softbuffer::Pixel;
23
use std::num::NonZeroU32;
34
use winit::event::{KeyEvent, WindowEvent};
45
use winit::event_loop::{ControlFlow, EventLoop};
@@ -52,12 +53,8 @@ fn main() {
5253
let mut buffer = surface.buffer_mut().unwrap();
5354
let width = fruit.width();
5455
for (x, y, pixel) in fruit.pixels() {
55-
let red = pixel.0[0] as u32;
56-
let green = pixel.0[1] as u32;
57-
let blue = pixel.0[2] as u32;
58-
59-
let color = blue | (green << 8) | (red << 16);
60-
buffer[(y * width + x) as usize] = color;
56+
let pixel = Pixel::new_rgb(pixel.0[0], pixel.0[1], pixel.0[2]);
57+
buffer[(y * width + x) as usize] = pixel;
6158
}
6259

6360
buffer.present().unwrap();

examples/libxcb.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ mod example {
1616
xcb_ffi::XCBConnection,
1717
};
1818

19-
const RED: u32 = 255 << 16;
20-
2119
pub(crate) fn run() {
2220
// Create a new XCB connection
2321
let (conn, screen) = XCBConnection::connect(None).expect("Failed to connect to X server");
@@ -113,7 +111,7 @@ mod example {
113111
)
114112
.unwrap();
115113
let mut buffer = surface.buffer_mut().unwrap();
116-
buffer.fill(RED);
114+
buffer.fill(softbuffer::Pixel::new_rgb(0xff, 0, 0));
117115
buffer.present().unwrap();
118116
}
119117
Event::ConfigureNotify(configure_notify) => {

examples/rectangle.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
2-
use softbuffer::Buffer;
2+
use softbuffer::{Buffer, Pixel};
33
use std::num::NonZeroU32;
44
use winit::event::{ElementState, KeyEvent, WindowEvent};
55
use winit::event_loop::{ControlFlow, EventLoop};
@@ -14,12 +14,12 @@ fn redraw(buffer: &mut Buffer<'_, impl HasDisplayHandle, impl HasWindowHandle>,
1414
for y in 0..height {
1515
for x in 0..width {
1616
let value = if flag && x >= 100 && x < width - 100 && y >= 100 && y < height - 100 {
17-
0x00ffffff
17+
Pixel::new_rgb(0xff, 0xff, 0xff)
1818
} else {
1919
let red = (x & 0xff) ^ (y & 0xff);
2020
let green = (x & 0x7f) ^ (y & 0x7f);
2121
let blue = (x & 0x3f) ^ (y & 0x3f);
22-
blue | (green << 8) | (red << 16)
22+
Pixel::new_rgb(red as u8, green as u8, blue as u8)
2323
};
2424
buffer[(y * width + x) as usize] = value;
2525
}

examples/winit.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,11 @@ pub(crate) fn entry(event_loop: EventLoop<()>) {
4747
let mut buffer = surface.buffer_mut().unwrap();
4848
for y in 0..buffer.height().get() {
4949
for x in 0..buffer.width().get() {
50-
let red = x % 255;
51-
let green = y % 255;
52-
let blue = (x * y) % 255;
50+
let red = (x % 255) as u8;
51+
let green = (y % 255) as u8;
52+
let blue = ((x * y) % 255) as u8;
5353
let index = y * buffer.width().get() + x;
54-
buffer[index as usize] = blue | (green << 8) | (red << 16);
54+
buffer[index as usize] = softbuffer::Pixel::new_rgb(red, green, blue);
5555
}
5656
}
5757

0 commit comments

Comments
 (0)