-
Notifications
You must be signed in to change notification settings - Fork 87
Description
Hey! I'm working on improving Softbuffer, a library for creating a buffer that can be rendered on the CPU and presented to a window. I believe that tiny-skia and vello_cpu are good complements for it, and I'll be recommending them in our documentation in rust-windowing/softbuffer#325.
For us to be zero-copy on Android and macOS, we need to expose stride, see rust-windowing/softbuffer#315. This is unfortunate though, because it means that integration with tiny-skia when stride != width requires rendering into a separate buffer first.
Would it be possible (and desirable) for tiny-skia to support passing a byte stride != width * 4 in their creation methods?
Note that this might not be that useful yet, since a lot of platforms still only support BGRA pixel formats, so users of tiny-skia would still have to copy in any case then. I plan to improve that, such that in the future an integration between these two libraries would look like:
// Set surface as transparent and try to use an RGBA pixel format.
surface.set_alpha_mode(AlphaMode::Premultiplied);
let needs_rgba_conversion = surface.supported_pixel_formats().contains(PixelFormat::Rgba8) {
surface.set_alpha_mode(PixelFormat::Rgba8);
false
} else {
// Ideally supported on most platforms, this would only be a fallback in edge cases.
// (e.g. Wayland compositors aren't guaranteed to support RGBA, but most do).
surface.set_pixel_format(PixelFormat::Bgra8);
true
};
// Get next buffer.
let buffer = surface.next_buffer().unwrap();
// Create `PixmapMut<'_>` from `Buffer<'_>`.
let width = buffer.width();
let height = buffer.height();
let byte_stride = buffer.byte_stride();
let data = buffer.data();
let pixmap = PixmapMut::from_bytes(data, byte_stride, width, height);
draw(pixmap); // User draws here.
if needs_rgba_conversion {
// Swap red and blue channel to convert RGBA to BGRA.
for row in buffer.rows() {
for [r, _g, b, _a] in row.as_chunks::<4>() {
std::mem::swap(r, b);
}
}
}
// Present the image.
buffer.present();That would fully avoid allocating unnecessary buffers, and would only add an extra processing step (swapping the r and b channels, which could probably be vectorized quite a bit) if absolutely necessary. (If you wanted to avoid that too, you'd have to make the order of PremultipliedColorU8 platform-dependent. This is what Softbuffer is gonna do in its default mode, but it is probably gonna be too annoying for tiny-skia).