Croissant Runtime
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
crsn/crsn_screen/src/exec.rs

100 lines
3.0 KiB

use std::collections::{HashMap, VecDeque};
use crsn::asm::data::literal::Value;
use crsn::asm::instr::Cond;
use crsn::module::{CrsnExtension, EvalRes, OpTrait};
use crsn::runtime::fault::Fault;
use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
use crate::defs::ScreenOp;
use minifb::{Window, WindowOptions, ScaleMode};
use parking_lot::Mutex;
use std::sync::Arc;
#[derive(Debug, Default)]
struct Backend {
width: usize,
height: usize,
buffer: Vec<u32>,
window: Option<Window>,
}
// Hack for Window
unsafe impl std::marker::Send for Backend { }
impl OpTrait for ScreenOp {
fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
let eres = EvalRes::default();
match self {
ScreenOp::ScreenInit { width, height } => {
let w = state.read(*width)?;
let h = state.read(*height)?;
init(state, w, h)?;
}
ScreenOp::SetPixel { x, y, color } => {
let x = state.read(*x)?;
let y = state.read(*y)?;
let color = state.read(*color)?;
let backend : &mut Backend = state.ext_mut();
match &mut backend.window {
Some(w) => {
let index = y * backend.width as u64 + x;
if index as usize > backend.buffer.len() {
warn!("Screen set pixel out of bounds");
state.set_flag(Cond::Invalid, true);
} else {
backend.buffer[index as usize] = color as u32;
w
.update_with_buffer(&backend.buffer, backend.width, backend.height)
.expect("Update screen"); // TODO fault
}
}
None => {
state.set_flag(Cond::Invalid, true);
}
}
}
}
Ok(eres)
}
//
}
fn init(state: &mut RunState, width: Value, height: Value) -> Result<(), Fault> {
let mut window = Window::new(
"Croissant",
width as usize,
height as usize,
WindowOptions {
resize: true,
scale_mode: ScaleMode::AspectRatioStretch,
..WindowOptions::default()
},
).expect("Unable to create window"); // TODO fault
let backend : &mut Backend = state.ext_mut();
if backend.window.is_some() {
return Err(Fault::NotAllowed("Screen already initialized".into()));
}
backend.width = width as usize;
backend.height = height as usize;
backend.buffer = vec![0; (width * height) as usize];
// window.limit_update_rate(Some(std::time::Duration::from_micros(16600)));
window.limit_update_rate(None);
window
.update_with_buffer(&backend.buffer, backend.width, backend.height)
.expect("Update screen"); // TODO fault
backend.window = Some(window);
Ok(())
}