use drmkit_planes::{Layer as PlaneLayer, PropTag};
use crate::display::{DisplayParams, to_16_16};
use crate::source::{BindingModel, SourceFormat};
#[derive(Debug, Clone, Copy)]
#[allow(
clippy::exhaustive_structs,
reason = "built by callers, with no default to fill a new field from"
)]
pub struct LoweringInput {
pub display: DisplayParams,
pub format: SourceFormat,
pub binding: BindingModel,
pub fb_id: u32,
pub crtc_id: u32,
pub default_zpos: Option<u64>,
}
pub fn lower_layer(input: &LoweringInput, dst: &mut PlaneLayer) {
let display = &input.display;
let format = input.format;
let driver_owns_binding = input.binding == BindingModel::DriverOwnsBinding;
dst.set_externally_bound(driver_owns_binding);
if !driver_owns_binding {
dst.set_property(PropTag::FbId, u64::from(input.fb_id));
}
dst.set_property(PropTag::CrtcId, u64::from(input.crtc_id));
dst.set_property(
PropTag::CrtcX,
u64::from(display.dst_rect.x.cast_unsigned()),
);
dst.set_property(
PropTag::CrtcY,
u64::from(display.dst_rect.y.cast_unsigned()),
);
dst.set_property(PropTag::CrtcW, u64::from(display.dst_rect.w));
dst.set_property(PropTag::CrtcH, u64::from(display.dst_rect.h));
if let Some(fixed) = display.src_rect_fixed {
let extent = |value: u32, full: u32| {
if value == 0 {
to_16_16(full)
} else {
u64::from(value)
}
};
dst.set_property(PropTag::SrcX, u64::from(fixed.x));
dst.set_property(PropTag::SrcY, u64::from(fixed.y));
dst.set_property(PropTag::SrcW, extent(fixed.w, format.width));
dst.set_property(PropTag::SrcH, extent(fixed.h, format.height));
} else {
let src_w = if display.src_rect.w == 0 {
format.width
} else {
display.src_rect.w
};
let src_h = if display.src_rect.h == 0 {
format.height
} else {
display.src_rect.h
};
dst.set_property(PropTag::SrcX, to_16_16(display.src_rect.x.cast_unsigned()));
dst.set_property(PropTag::SrcY, to_16_16(display.src_rect.y.cast_unsigned()));
dst.set_property(PropTag::SrcW, to_16_16(src_w));
dst.set_property(PropTag::SrcH, to_16_16(src_h));
}
dst.set_property(PropTag::PixelFormat, u64::from(format.fourcc));
dst.set_property(PropTag::FbModifier, format.modifier);
if display.rotation != 0 {
dst.set_property(PropTag::Rotation, display.rotation);
}
if let Some(zpos) = display.zpos.or(input.default_zpos) {
dst.set_property(PropTag::Zpos, zpos);
}
if let Some(alpha) = display.alpha {
dst.set_property(PropTag::Alpha, u64::from(alpha));
}
}