Skip to content

Commit a695ee3

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 8f87c1b commit a695ee3

File tree

4 files changed

+26
-8
lines changed

4 files changed

+26
-8
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: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::{
22
backend_interface::*,
33
error::{InitError, SwResultExt},
4-
Pixel, Rect, SoftBufferError,
4+
util, Pixel, Rect, SoftBufferError,
55
};
66
use raw_window_handle::{HasDisplayHandle, HasWindowHandle, RawDisplayHandle, RawWindowHandle};
77
use std::{
@@ -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: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,19 @@ impl ops::DerefMut for PixelBuffer {
6565
&mut self.0
6666
}
6767
}
68+
69+
/// Compute the byte stride desired by Softbuffer when a platform can use any stride.
70+
///
71+
/// TODO(madsmtm): This should take the pixel format / bit depth as input after:
72+
/// <https://github.com/rust-windowing/softbuffer/issues/98>
73+
#[inline]
74+
pub(crate) fn byte_stride(width: u32) -> u32 {
75+
let row_alignment = if cfg!(debug_assertions) {
76+
16 // Use a higher alignment to help users catch issues with their stride calculations.
77+
} else {
78+
4 // At least 4 is necessary for `Buffer` to return `&mut [u32]`.
79+
};
80+
// TODO: Use `next_multiple_of` when in MSRV.
81+
let mask = row_alignment * 4 - 1;
82+
((width * 32 + mask) & !mask) >> 3
83+
}

0 commit comments

Comments
 (0)