100 lines
2.3 KiB
Rust
100 lines
2.3 KiB
Rust
use super::shm_pool::ShmPool;
|
|
use bevy::{
|
|
asset::{Assets, Handle, RenderAssetUsages},
|
|
image::Image,
|
|
render::render_resource::{Extent3d, TextureDimension, TextureFormat},
|
|
};
|
|
use mint::Vector2;
|
|
use std::sync::Arc;
|
|
use waynest::server::protocol::core::wayland::wl_shm::Format;
|
|
/// Parameters for a shared memory buffer
|
|
#[derive(Debug)]
|
|
pub struct ShmBufferBacking {
|
|
pool: Arc<ShmPool>,
|
|
offset: usize,
|
|
stride: usize,
|
|
size: Vector2<usize>,
|
|
format: Format,
|
|
}
|
|
|
|
impl ShmBufferBacking {
|
|
pub fn new(
|
|
pool: Arc<ShmPool>,
|
|
offset: usize,
|
|
stride: usize,
|
|
size: Vector2<usize>,
|
|
format: Format,
|
|
) -> Self {
|
|
Self {
|
|
pool,
|
|
offset,
|
|
stride,
|
|
size,
|
|
format,
|
|
}
|
|
}
|
|
|
|
#[tracing::instrument("debug", skip_all)]
|
|
pub fn update_tex(&self, images: &mut Assets<Image>) -> Option<Handle<Image>> {
|
|
let src_data_lock = self.pool.data_lock();
|
|
let mut src_cursor = self.offset;
|
|
|
|
// Calculate maximum cursor position needed - stride is already in bytes
|
|
let max_cursor = self.offset + (self.size.y * self.stride);
|
|
|
|
// Check if we have enough data
|
|
if max_cursor > src_data_lock.len() {
|
|
return None;
|
|
}
|
|
let data_len = self.size.x * self.size.y * 4;
|
|
if src_data_lock.len() != data_len {
|
|
return None;
|
|
}
|
|
let mut dst_cursor = 0;
|
|
|
|
let mut dst_data = vec![0u8; data_len];
|
|
for _y in 0..self.size.y {
|
|
for _x in 0..self.size.x {
|
|
match self.format {
|
|
Format::Argb8888 | Format::Xrgb8888 => {
|
|
dst_data[dst_cursor] = src_data_lock[src_cursor + 2]; // Red is byte 2
|
|
dst_data[dst_cursor + 1] = src_data_lock[src_cursor + 1]; // Green is byte 1
|
|
dst_data[dst_cursor + 2] = src_data_lock[src_cursor]; // Blue is byte 0
|
|
dst_data[dst_cursor + 3] = src_data_lock[src_cursor + 3]; // Alpha is byte 3
|
|
}
|
|
_ => panic!("Unsupported format {:?}", self.format),
|
|
}
|
|
src_cursor += 4;
|
|
dst_cursor += 4;
|
|
}
|
|
src_cursor += self.stride - (self.size.x * 4);
|
|
}
|
|
|
|
let image = Image::new(
|
|
Extent3d {
|
|
width: self.size().x as u32,
|
|
height: self.size().y as u32,
|
|
depth_or_array_layers: 1,
|
|
},
|
|
TextureDimension::D2,
|
|
dst_data,
|
|
TextureFormat::Rgba8UnormSrgb,
|
|
RenderAssetUsages::RENDER_WORLD,
|
|
);
|
|
|
|
Some(images.add(image))
|
|
}
|
|
|
|
pub fn is_transparent(&self) -> bool {
|
|
match self.format {
|
|
Format::Xrgb8888 => false,
|
|
Format::Argb8888 => true,
|
|
_ => true,
|
|
}
|
|
}
|
|
|
|
pub fn size(&self) -> Vector2<usize> {
|
|
self.size
|
|
}
|
|
}
|