use crate::{PropertyWrite, SurfaceRef};
#[derive(Debug, Clone, Copy, Default)]
#[non_exhaustive]
pub struct PlaneSlot {
pub plane_id: u32,
pub crtc_id: u32,
pub fb_id_prop: u32,
pub crtc_id_prop: u32,
pub crtc_x_prop: u32,
pub crtc_y_prop: u32,
pub crtc_w_prop: u32,
pub crtc_h_prop: u32,
pub src_x_prop: u32,
pub src_y_prop: u32,
pub src_w_prop: u32,
pub src_h_prop: u32,
pub blend_mode_prop: u32,
pub blend_mode_value: u64,
pub alpha_prop: u32,
pub zpos_prop: u32,
pub zpos_value: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
#[non_exhaustive]
pub enum PlaneError {
#[error("{surfaces} decorations for {slots} reserved planes")]
TooManySurfaces {
surfaces: usize,
slots: usize,
},
}
pub fn compute_writes(
slots: &[PlaneSlot],
surfaces: &[SurfaceRef],
) -> Result<Vec<PropertyWrite>, PlaneError> {
if surfaces.len() > slots.len() {
return Err(PlaneError::TooManySurfaces {
surfaces: surfaces.len(),
slots: slots.len(),
});
}
let mut writes = Vec::with_capacity(slots.len() * 12);
let mut add = |object_id: u32, property_id: u32, value: u64| {
writes.push(PropertyWrite {
object_id,
property_id,
value,
});
};
for (index, slot) in slots.iter().enumerate() {
let armed = surfaces.get(index).copied().filter(|s| s.is_armed());
let Some(surface) = armed else {
add(slot.plane_id, slot.fb_id_prop, 0);
add(slot.plane_id, slot.crtc_id_prop, 0);
continue;
};
add(slot.plane_id, slot.fb_id_prop, u64::from(surface.fb_id));
add(slot.plane_id, slot.crtc_id_prop, u64::from(slot.crtc_id));
add(
slot.plane_id,
slot.crtc_x_prop,
i64::from(surface.x).cast_unsigned(),
);
add(
slot.plane_id,
slot.crtc_y_prop,
i64::from(surface.y).cast_unsigned(),
);
add(slot.plane_id, slot.crtc_w_prop, u64::from(surface.width));
add(slot.plane_id, slot.crtc_h_prop, u64::from(surface.height));
add(slot.plane_id, slot.src_x_prop, 0);
add(slot.plane_id, slot.src_y_prop, 0);
add(slot.plane_id, slot.src_w_prop, to_16_16(surface.width));
add(slot.plane_id, slot.src_h_prop, to_16_16(surface.height));
if slot.blend_mode_prop != 0 {
add(slot.plane_id, slot.blend_mode_prop, slot.blend_mode_value);
}
if slot.alpha_prop != 0 {
add(slot.plane_id, slot.alpha_prop, 0xFFFF);
}
if slot.zpos_prop != 0 {
add(slot.plane_id, slot.zpos_prop, slot.zpos_value);
}
}
Ok(writes)
}
const fn to_16_16(value: u32) -> u64 {
(value as u64) << 16
}