Skip to content

Commit 9677e98

Browse files
committed
Use higher stride on some platforms when cfg(debug_assertions)
To help with debugging incorrect stride/width calculations, it helps that there are more common backends (than Android) that have `stride != width * 4`.
1 parent 25ba8f2 commit 9677e98

File tree

4 files changed

+26
-7
lines changed

4 files changed

+26
-7
lines changed

src/backends/cg.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,9 @@ impl<D: HasDisplayHandle, W: HasWindowHandle> SurfaceInterface<D, W> for CGImpl<
259259
}
260260

261261
fn buffer_mut(&mut self) -> Result<BufferImpl<'_>, SoftBufferError> {
262+
let buffer_size = util::byte_stride(self.width as u32) as usize * self.height / 4;
262263
Ok(BufferImpl {
263-
buffer: util::PixelBuffer(vec![Pixel::default(); self.width * self.height]),
264+
buffer: util::PixelBuffer(vec![Pixel::default(); buffer_size]),
264265
width: self.width,
265266
height: self.height,
266267
color_space: &self.color_space,
@@ -280,7 +281,7 @@ pub struct BufferImpl<'a> {
280281

281282
impl BufferInterface for BufferImpl<'_> {
282283
fn byte_stride(&self) -> NonZeroU32 {
283-
NonZeroU32::new(self.width().get() * 4).unwrap()
284+
NonZeroU32::new(util::byte_stride(self.width as u32)).unwrap()
284285
}
285286

286287
fn width(&self) -> NonZeroU32 {
@@ -342,7 +343,7 @@ impl BufferInterface for BufferImpl<'_> {
342343
self.height,
343344
8,
344345
32,
345-
self.width * 4,
346+
util::byte_stride(self.width as u32) as usize,
346347
Some(self.color_space),
347348
bitmap_info,
348349
Some(&data_provider),

src/backends/wayland/buffer.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use wayland_client::{
1515
};
1616

1717
use super::State;
18+
use crate::util;
1819
use crate::Pixel;
1920

2021
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
@@ -99,7 +100,7 @@ impl WaylandBuffer {
99100
0,
100101
width,
101102
height,
102-
width * 4,
103+
util::byte_stride(width as u32) as i32,
103104
// This is documented as `0xXXRRGGBB` on a little-endian machine, which means a byte
104105
// order of `[B, G, R, X]`.
105106
wl_shm::Format::Xrgb8888,
@@ -141,7 +142,7 @@ impl WaylandBuffer {
141142
0,
142143
width,
143144
height,
144-
width * 4,
145+
util::byte_stride(width as u32) as i32,
145146
wl_shm::Format::Xrgb8888,
146147
&self.qh,
147148
self.released.clone(),
@@ -161,7 +162,7 @@ impl WaylandBuffer {
161162
}
162163

163164
fn len(&self) -> usize {
164-
self.width as usize * self.height as usize
165+
util::byte_stride(self.width as u32) as usize * self.height as usize / 4
165166
}
166167

167168
#[inline]

src/backends/wayland/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ pub struct BufferImpl<'a> {
220220

221221
impl BufferInterface for BufferImpl<'_> {
222222
fn byte_stride(&self) -> NonZeroU32 {
223-
NonZeroU32::new(self.width as u32 * 4).unwrap()
223+
NonZeroU32::new(util::byte_stride(self.width as u32)).unwrap()
224224
}
225225

226226
fn width(&self) -> NonZeroU32 {

src/util.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,20 @@ pub(crate) fn to_i16_saturating(val: u32) -> i16 {
9696
pub(crate) fn to_i32_saturating(val: u32) -> i32 {
9797
val.try_into().unwrap_or(i32::MAX)
9898
}
99+
100+
/// Compute the byte stride desired by Softbuffer when a platform can use any stride.
101+
///
102+
/// TODO(madsmtm): This should take the pixel format / bit depth as input after:
103+
/// <https://github.com/rust-windowing/softbuffer/issues/98>
104+
#[inline]
105+
pub(crate) fn byte_stride(width: u32) -> u32 {
106+
let row_alignment = if cfg!(debug_assertions) {
107+
16 // Use a higher alignment to help users catch issues with their stride calculations.
108+
} else {
109+
4 // At least 4 is necessary for `Buffer` to return `&mut [u32]`.
110+
};
111+
// TODO: Use `next_multiple_of` when in MSRV.
112+
let mask = row_alignment * 4 - 1;
113+
((width * 32 + mask) & !mask) >> 3
114+
}
115+

0 commit comments

Comments
 (0)