use core::mem::MaybeUninit;
pub use kernel_user_link::graphics::{FrameBufferInfo, GraphicsCommand};
use kernel_user_link::{
call_syscall,
syscalls::{SyscallError, SYS_GRAPHICS},
};
pub struct BlitCommand<'a> {
pub memory: &'a [u8],
pub src_framebuffer_info: FrameBufferInfo,
pub src: (usize, usize),
pub dst: (usize, usize),
pub size: (usize, usize),
}
impl BlitCommand<'_> {
fn is_buffer_valid(&self) -> bool {
let buf_expected_len = self.src_framebuffer_info.memory_size();
if self.memory.len() != buf_expected_len {
return false;
}
if self.src.0 >= self.src_framebuffer_info.width
|| self.src.1 >= self.src_framebuffer_info.height
|| self.src.0 + self.size.0 > self.src_framebuffer_info.width
|| self.src.1 + self.size.1 > self.src_framebuffer_info.height
{
return false;
}
true
}
}
unsafe fn graphics(command: GraphicsCommand, extra: u64) -> Result<(), SyscallError> {
unsafe {
call_syscall!(
SYS_GRAPHICS,
command as u64, extra, )
.map(|e| assert!(e == 0))
}
}
pub fn take_ownership() -> Result<(), SyscallError> {
unsafe { graphics(GraphicsCommand::TakeOwnership, 0) }
}
pub fn release_ownership() -> Result<(), SyscallError> {
unsafe { graphics(GraphicsCommand::ReleaseOwnership, 0) }
}
pub fn get_framebuffer_info() -> Result<FrameBufferInfo, SyscallError> {
let mut info = MaybeUninit::<FrameBufferInfo>::uninit();
unsafe {
graphics(
GraphicsCommand::GetFrameBufferInfo,
info.as_mut_ptr() as *const _ as u64,
)?;
}
unsafe { Ok(info.assume_init()) }
}
pub fn blit(command: &BlitCommand<'_>) -> Result<(), SyscallError> {
if !command.is_buffer_valid() {
return Err(SyscallError::InvalidGraphicsBuffer);
}
let converted_command = kernel_user_link::graphics::BlitCommand {
memory: command.memory.as_ptr(),
src_framebuffer_info: command.src_framebuffer_info,
src: command.src,
dst: command.dst,
size: command.size,
};
unsafe { graphics(GraphicsCommand::Blit, &converted_command as *const _ as u64) }
}