use alloc::vec::Vec;
use super::disp::{disp_backend, BK_WAYLAND, BK_X11};
pub const GPU_BUF_PENDING: u32 = 0;
pub const GPU_BUF_FREE: u32 = 1;
pub const GPU_BUF_BUSY: u32 = 2;
pub const GPU_BUF_FAILED: u32 = 3;
#[derive(Clone, Debug, Default)]
pub struct GpuCaps {
pub device: Option<u64>,
pub formats: Vec<(u32, u64)>,
}
#[derive(Clone, Copy, Debug)]
pub struct GpuPlane {
pub fd: i32,
pub offset: u32,
pub stride: u32,
}
#[derive(Clone, Debug)]
pub struct GpuBufDesc {
pub w: i32,
pub h: i32,
pub fourcc: u32,
pub modifier: u64,
pub planes: Vec<GpuPlane>,
}
#[derive(Clone, Debug)]
pub struct NativeWindow {
pub caps: GpuCaps,
pub size: (i32, i32),
}
pub fn win_gpu_child(w: i32) -> Option<NativeWindow> {
if crate::env("jfgui_GPU_DMABUF").as_deref() == Some("0") {
return None; }
let caps = match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_caps(),
BK_X11 => super::x11::gpux::gpu_caps(w),
_ => None,
}?;
if caps.formats.is_empty() {
return None;
}
Some(NativeWindow { caps, size: crate::win_size(w) })
}
pub fn win_gpu_child_show(_w: i32, _show: bool) {}
pub fn win_release_kept(_w: i32) {}
pub fn win_gpu_child_later(_w: i32) -> bool {
false
}
pub fn win_gpu_child_alone(_w: i32) -> bool {
true
}
pub fn gpu_out_state(_state: u32) {}
pub fn gpu_thread_spawn(stack: usize, f: alloc::boxed::Box<dyn FnOnce() + Send>) -> Option<crate::Thread> {
crate::thread_spawn(stack, f)
}
pub fn win_in_sizemove() -> bool {
false
}
pub fn win_display_adapter(_w: i32) -> Option<(u32, u32)> {
None
}
pub fn win_remote_session() -> bool {
false
}
pub fn gpu_buf_new(w: i32, d: &GpuBufDesc) -> u32 {
if crate::env("jfgui_GPU_DMABUF").as_deref() == Some("refuse") {
close_planes(d); return 0;
}
match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_buf_new(w, d),
BK_X11 => super::x11::gpux::gpu_buf_new(w, d),
_ => {
close_planes(d);
0
}
}
}
pub(crate) fn close_planes(d: &GpuBufDesc) {
for p in &d.planes {
unsafe { rt::os::syscall3(rt::os::SYS_CLOSE, p.fd as usize, 0, 0) };
}
}
pub fn gpu_buf_state(w: i32, h: u32) -> u32 {
match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_buf_state(w, h),
BK_X11 => super::x11::gpux::gpu_buf_state(w, h),
_ => GPU_BUF_FAILED,
}
}
pub fn gpu_buf_free(w: i32, h: u32) {
match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_buf_free(w, h),
BK_X11 => super::x11::gpux::gpu_buf_free(w, h),
_ => {}
}
}
pub fn gpu_can_show(w: i32) -> bool {
match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_can_show(w),
BK_X11 => super::x11::gpux::gpu_can_show(w),
_ => false,
}
}
pub fn gpu_show(w: i32, h: u32, rects: Option<&[[i32; 4]]>) {
match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_show(w, h, rects),
BK_X11 => super::x11::gpux::gpu_show(w, h, rects),
_ => {}
}
}
pub fn gpu_next_look(w: i32) -> u64 {
match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_next_look(w),
BK_X11 => super::x11::gpux::gpu_next_look(w),
_ => u64::MAX,
}
}
pub fn gpu_wait(deadline_us: u64) {
let now = crate::time_us();
let ms = (deadline_us.saturating_sub(now).div_ceil(1000)).min(1000) as i32;
match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_pump(ms),
BK_X11 => super::x11::gpux::gpu_pump(ms),
_ => crate::sleep_ms(ms as u32),
}
}
pub const WT_PIXEL: u32 = 1;
pub const WT_REDRAW: u32 = 2;
pub const WT_MOVE: u32 = 3;
pub const WT_DPI: u32 = 4;
pub const WT_POPUP_RECT: u32 = 7;
pub const WT_NOANIM: u32 = 16;
pub const WT_FROM_POINT: u32 = 17;
pub const WT_SHOW: u32 = 18;
pub fn win_test(op: u32, w: i32, a: [i32; 4]) -> i64 {
match op {
WT_PIXEL => match disp_backend() {
BK_WAYLAND => match super::wl::gpuw::gpu_test_shm(w) {
Some((iw, ih, px)) if a[0] >= 0 && a[1] >= 0 && a[0] < iw && a[1] < ih => {
let o = (a[1] as usize * iw as usize + a[0] as usize) * 4;
px[o] as i64 | (px[o + 1] as i64) << 8 | (px[o + 2] as i64) << 16
}
_ => -1,
},
BK_X11 => super::x11::gpux::gpu_test_pixel(w, a[0], a[1]),
_ => -1,
},
WT_MOVE => {
crate::win_set_rect(w, a[0], a[1], a[2], a[3]);
crate::evq_push(crate::Event { typ: crate::E_RESIZE, x: a[2], y: a[3], win: w as u8, ..crate::Event::default() });
1
}
WT_DPI => match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_test_dpi(w, a[0]),
_ => -1,
},
WT_SHOW => {
if a[0] == 7 {
crate::win_cmd(w, crate::WCMD_MINIMIZE);
} else if disp_backend() == BK_WAYLAND {
super::wl::gpuw::gpu_test_unminimize(w);
} else {
crate::win_cmd(w, crate::WCMD_RESTORE);
}
1
}
WT_POPUP_RECT => match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_test_popup(w),
BK_X11 => super::x11::gpux::gpu_test_popup(w),
_ => -1,
},
_ => 1,
}
}
pub fn win_test_image(w: i32) -> Option<(i32, i32, Vec<u8>)> {
match disp_backend() {
BK_X11 => super::x11::gpux::gpu_test_image(w),
_ => None,
}
}
pub fn win_test_screen(_x: i32, _y: i32, _w: i32, _h: i32) -> Option<Vec<u8>> {
None
}
pub fn win_test_send(_w: i32, _msg: u32, _wp: usize, _lp: isize) -> isize {
0
}
pub fn win_test_usage() -> (u64, u64, u64) {
let mut ts = [0i64; 2];
unsafe { rt::os::syscall3(rt::os::SYS_CLOCK_GETTIME, 2, ts.as_mut_ptr() as usize, 0) };
let cpu = ts[0] as u64 * 1_000_000 + ts[1] as u64 / 1000;
let (mut rss, mut anon) = (0, 0);
if let Some(b) = super::sys::read_file_raw("/proc/self/status") {
for ln in b.split(|&c| c == b'\n') {
let val = |n: &[u8]| {
ln.strip_prefix(n).map_or(0u64, |r| r.iter().filter(|c| c.is_ascii_digit()).fold(0, |v, c| v * 10 + (c - b'0') as u64) * 1024)
};
rss = rss.max(val(b"VmRSS:"));
anon = anon.max(val(b"RssAnon:"));
}
}
(cpu, rss as u64, anon as u64)
}
pub fn gpu_test_presented() -> Vec<(u64, u64)> {
match disp_backend() {
BK_WAYLAND => super::wl::gpuw::gpu_test_presented(),
_ => Vec::new(),
}
}