use denise::{BufferAge, Frame, Size};
use crate::types::{DeniseFrame, DeniseRect, pixel_format};
use crate::{
DENISE_ERR_BUFFER_TOO_SMALL, DENISE_ERR_INVALID, DENISE_ERR_NO_NODE, DENISE_ERR_NULL,
DENISE_ERR_PANIC, DENISE_OK, DeniseUi, guard, handle,
};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_needs_paint(ui: *mut DeniseUi) -> bool {
guard(false, || {
match unsafe { handle(ui) } {
Some(handle) => handle.ui.needs_paint(),
None => false,
}
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_paint(ui: *mut DeniseUi, frame: *const DeniseFrame) -> i32 {
guard(DENISE_ERR_PANIC, || {
let Some(handle) = (unsafe { handle(ui) }) else {
return DENISE_ERR_NULL;
};
if frame.is_null() {
return DENISE_ERR_NULL;
}
let description = unsafe { frame.read() };
if description.pixels.is_null() {
return DENISE_ERR_NULL;
}
let Some(format) = pixel_format(description.format) else {
return DENISE_ERR_INVALID;
};
let size = Size::new(description.width, description.height);
if size.is_empty() || description.stride < description.width {
return DENISE_ERR_INVALID;
}
let required = description.stride as usize * (description.height as usize - 1)
+ description.width as usize;
if description.len < required {
return DENISE_ERR_BUFFER_TOO_SMALL;
}
let age = if description.buffer_age < 0 {
BufferAge::Undefined
} else {
BufferAge::Frames(description.buffer_age as u32)
};
let pixels = unsafe { std::slice::from_raw_parts_mut(description.pixels, description.len) };
let Ok(mut frame) = Frame::new(pixels, size, description.stride, format, age) else {
return DENISE_ERR_INVALID;
};
handle.ui.paint(&mut frame);
DENISE_OK
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_damage(
ui: *mut DeniseUi,
out: *mut DeniseRect,
cap: usize,
) -> isize {
guard(DENISE_ERR_PANIC as isize, || {
let Some(handle) = (unsafe { handle(ui) }) else {
return DENISE_ERR_NULL as isize;
};
let damage = handle.ui.damage();
if !out.is_null() {
for (index, rect) in damage.iter().take(cap).enumerate() {
unsafe { out.add(index).write((*rect).into()) };
}
}
damage.len() as isize
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_presented(ui: *mut DeniseUi) -> i32 {
guard(DENISE_ERR_PANIC, || {
let Some(handle) = (unsafe { handle(ui) }) else {
return DENISE_ERR_NULL;
};
handle.ui.presented();
DENISE_OK
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_invalidate_all(ui: *mut DeniseUi) -> i32 {
guard(DENISE_ERR_PANIC, || {
let Some(handle) = (unsafe { handle(ui) }) else {
return DENISE_ERR_NULL;
};
handle.ui.invalidate_all();
DENISE_OK
})
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn denise_ui_invalidate(ui: *mut DeniseUi, node: u64) -> i32 {
guard(DENISE_ERR_PANIC, || {
let Some(handle) = (unsafe { handle(ui) }) else {
return DENISE_ERR_NULL;
};
let id = denise_ui::NodeId::from_ffi(node);
if !handle.ui.contains(id) {
return DENISE_ERR_NO_NODE;
}
handle.ui.invalidate(id);
DENISE_OK
})
}