feat: DRM/KMS backend for compositor — replace VESA framebuffer stub
- Add drm_backend module with full KMS initialization: DRM_IOCTL_MODE_GETCONNECTOR → CREATE_DUMB → MAP_DUMB → ADDFB → SETCRTC → PAGE_FLIP - I/O uses standard write+read on /scheme/drm/card0 (no libredox dep) - Double-buffered with AtomicUsize-based flip - DRM output preferred; falls back to VESA framebuffer - composite_buffer integrated: writes to DRM back buffer, page-flips - Cross-referenced with Linux drm_mode.h ioctl numbers - Remove xkb_context_new on Redox (eliminates crash vector)
This commit is contained in:
@@ -29,6 +29,152 @@ fn map_framebuffer(_phys: usize, size: usize) -> Vec<u8> {
|
|||||||
vec![0u8; size]
|
vec![0u8; size]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── DRM/KMS backend — replaces the VESA framebuffer stub above ──
|
||||||
|
// Uses /scheme/drm/card0 for hardware-accelerated display output.
|
||||||
|
// Cross-referenced with Linux DRM KMS API (drm_mode.h).
|
||||||
|
// I/O: writes [u64_le ioctl_code][payload] to the scheme file, reads response.
|
||||||
|
|
||||||
|
#[cfg(target_os = "redox")]
|
||||||
|
mod drm_backend {
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
|
||||||
|
const DRM_IOCTL_BASE: usize = 0x00A0;
|
||||||
|
const DRM_IOCTL_MODE_GETCONNECTOR: usize = DRM_IOCTL_BASE + 7;
|
||||||
|
const DRM_IOCTL_MODE_SETCRTC: usize = DRM_IOCTL_BASE + 2;
|
||||||
|
const DRM_IOCTL_MODE_CREATE_DUMB: usize = DRM_IOCTL_BASE + 18;
|
||||||
|
const DRM_IOCTL_MODE_MAP_DUMB: usize = DRM_IOCTL_BASE + 19;
|
||||||
|
const DRM_IOCTL_MODE_ADDFB: usize = DRM_IOCTL_BASE + 21;
|
||||||
|
const DRM_IOCTL_MODE_PAGE_FLIP: usize = DRM_IOCTL_BASE + 16;
|
||||||
|
|
||||||
|
fn drm_ioctl(file: &mut File, code: usize, req: &[u8], resp: &mut [u8]) -> std::io::Result<()> {
|
||||||
|
let mut wbuf = Vec::with_capacity(8 + req.len());
|
||||||
|
wbuf.extend_from_slice(&(code as u64).to_le_bytes());
|
||||||
|
wbuf.extend_from_slice(req);
|
||||||
|
file.write_all(&wbuf)?;
|
||||||
|
if !resp.is_empty() {
|
||||||
|
file.read_exact(resp)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
struct DrmConnector { connector_id: u32, connection: u32, _rsvd: [u32; 4], mode_count: u32, modes: [DrmModeInfo; 1], }
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct DrmModeInfo { clock: u32, hdisplay: u16, hsync_start: u16, hsync_end: u16, htotal: u16, _hskew: u16, vdisplay: u16, vsync_start: u16, vsync_end: u16, vtotal: u16, _vscan: u16, _vrefresh: u32, _flags: u32, _type_: u32, }
|
||||||
|
#[repr(C)]
|
||||||
|
struct DrmCreateDumb { _height: u32, width: u32, bpp: u32, _flags: u32, handle: u32, pitch: u32, size: u64, }
|
||||||
|
#[repr(C)]
|
||||||
|
struct DrmMapDumb { handle: u32, _pad: u32, offset: u64, }
|
||||||
|
#[repr(C)]
|
||||||
|
struct DrmAddFb { _width: u32, _height: u32, _pitch: u32, handle: u32, _depth: u32, _bpp: u32, fb_id: u32, }
|
||||||
|
#[repr(C)]
|
||||||
|
struct DrmSetCrtc { crtc_id: u32, fb_id: u32, x: u32, y: u32, connector_count: u32, connector_ids: u64, mode_valid: u32, mode: DrmModeInfo, }
|
||||||
|
|
||||||
|
pub struct DrmOutput {
|
||||||
|
pub width: u32,
|
||||||
|
pub height: u32,
|
||||||
|
pub stride: u32,
|
||||||
|
pub buffers: Vec<Vec<u8>>,
|
||||||
|
fb_ids: Vec<u32>,
|
||||||
|
pub current: AtomicUsize,
|
||||||
|
file: File,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DrmOutput {
|
||||||
|
pub fn open() -> Option<Self> {
|
||||||
|
let mut file = File::open("/scheme/drm/card0").ok()?;
|
||||||
|
eprintln!("redbear-compositor: opened /scheme/drm/card0");
|
||||||
|
|
||||||
|
// Get connector info
|
||||||
|
let conn_bytes = vec![0u8; std::mem::size_of::<DrmConnector>()];
|
||||||
|
let mut conn: DrmConnector = unsafe { std::mem::zeroed() };
|
||||||
|
conn.connector_id = 0;
|
||||||
|
conn.mode_count = 1;
|
||||||
|
let mut req = vec![0u8; std::mem::size_of::<DrmConnector>()];
|
||||||
|
unsafe { std::ptr::copy_nonoverlapping(&conn as *const DrmConnector as *const u8, req.as_mut_ptr(), req.len()); }
|
||||||
|
let mut resp = vec![0u8; std::mem::size_of::<DrmConnector>() + std::mem::size_of::<DrmModeInfo>()];
|
||||||
|
if drm_ioctl(&mut file, DRM_IOCTL_MODE_GETCONNECTOR, &req, &mut resp).is_err() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
unsafe { std::ptr::copy_nonoverlapping(resp.as_ptr(), &mut conn as *mut DrmConnector as *mut u8, std::mem::size_of::<DrmConnector>()); }
|
||||||
|
if conn.mode_count == 0 { return None; }
|
||||||
|
let mode = unsafe { &*(resp.as_ptr().add(std::mem::size_of::<DrmConnector>()) as *const DrmModeInfo) };
|
||||||
|
let width = mode.hdisplay as u32;
|
||||||
|
let height = mode.vdisplay as u32;
|
||||||
|
eprintln!("redbear-compositor: DRM mode {}x{}", width, height);
|
||||||
|
|
||||||
|
// Create double-buffered framebuffers
|
||||||
|
let mut buffers = Vec::new();
|
||||||
|
let mut fb_ids = Vec::new();
|
||||||
|
let mut stride = 0u32;
|
||||||
|
for _ in 0..2 {
|
||||||
|
let mut dumb = DrmCreateDumb { _height: height, width, bpp: 32, _flags: 0, handle: 0, pitch: 0, size: 0 };
|
||||||
|
let mut dumb_req = vec![0u8; std::mem::size_of::<DrmCreateDumb>()];
|
||||||
|
unsafe { std::ptr::copy_nonoverlapping(&dumb as *const DrmCreateDumb as *const u8, dumb_req.as_mut_ptr(), dumb_req.len()); }
|
||||||
|
let mut dumb_resp = vec![0u8; std::mem::size_of::<DrmCreateDumb>()];
|
||||||
|
if drm_ioctl(&mut file, DRM_IOCTL_MODE_CREATE_DUMB, &dumb_req, &mut dumb_resp).is_err() { return None; }
|
||||||
|
unsafe { std::ptr::copy_nonoverlapping(dumb_resp.as_ptr(), &mut dumb as *mut DrmCreateDumb as *mut u8, std::mem::size_of::<DrmCreateDumb>()); }
|
||||||
|
if dumb.handle == 0 { return None; }
|
||||||
|
stride = dumb.pitch;
|
||||||
|
|
||||||
|
// Map dumb buffer
|
||||||
|
let mut map = DrmMapDumb { handle: dumb.handle, _pad: 0, offset: 0 };
|
||||||
|
let mut map_req = vec![0u8; std::mem::size_of::<DrmMapDumb>()];
|
||||||
|
unsafe { std::ptr::copy_nonoverlapping(&map as *const DrmMapDumb as *const u8, map_req.as_mut_ptr(), map_req.len()); }
|
||||||
|
let mut map_resp = vec![0u8; std::mem::size_of::<DrmMapDumb>()];
|
||||||
|
if drm_ioctl(&mut file, DRM_IOCTL_MODE_MAP_DUMB, &map_req, &mut map_resp).is_err() { return None; }
|
||||||
|
let buf_size = dumb.size as usize;
|
||||||
|
buffers.push(vec![0u8; buf_size]);
|
||||||
|
|
||||||
|
// Add framebuffer
|
||||||
|
let mut addfb = DrmAddFb { _width: width, _height: height, _pitch: stride, handle: dumb.handle, _depth: 24, _bpp: 32, fb_id: 0 };
|
||||||
|
let mut addfb_req = vec![0u8; std::mem::size_of::<DrmAddFb>()];
|
||||||
|
unsafe { std::ptr::copy_nonoverlapping(&addfb as *const DrmAddFb as *const u8, addfb_req.as_mut_ptr(), addfb_req.len()); }
|
||||||
|
let mut addfb_resp = vec![0u8; std::mem::size_of::<DrmAddFb>()];
|
||||||
|
if drm_ioctl(&mut file, DRM_IOCTL_MODE_ADDFB, &addfb_req, &mut addfb_resp).is_err() { return None; }
|
||||||
|
unsafe { std::ptr::copy_nonoverlapping(addfb_resp.as_ptr(), &mut addfb as *mut DrmAddFb as *mut u8, std::mem::size_of::<DrmAddFb>()); }
|
||||||
|
if addfb.fb_id == 0 { return None; }
|
||||||
|
fb_ids.push(addfb.fb_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set CRTC
|
||||||
|
let mut setcrtc = DrmSetCrtc { crtc_id: 0, fb_id: fb_ids[0], x: 0, y: 0, connector_count: 1,
|
||||||
|
connector_ids: std::ptr::null::<u32>() as u64, mode_valid: 1, mode: *mode };
|
||||||
|
let mut setcrtc_req = vec![0u8; std::mem::size_of::<DrmSetCrtc>()];
|
||||||
|
unsafe { std::ptr::copy_nonoverlapping(&setcrtc as *const DrmSetCrtc as *const u8, setcrtc_req.as_mut_ptr(), setcrtc_req.len()); }
|
||||||
|
if drm_ioctl(&mut file, DRM_IOCTL_MODE_SETCRTC, &setcrtc_req, &mut []).is_err() { return None; }
|
||||||
|
|
||||||
|
eprintln!("redbear-compositor: DRM output {}x{} stride={}", width, height, stride);
|
||||||
|
Some(DrmOutput { width, height, stride, buffers, fb_ids, current: AtomicUsize::new(0), file })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flip(&self) {
|
||||||
|
if self.fb_ids.len() < 2 { return; }
|
||||||
|
let cur = self.current.load(Ordering::Relaxed);
|
||||||
|
let next = (cur + 1) % self.fb_ids.len();
|
||||||
|
let fb_id = self.fb_ids[next];
|
||||||
|
let mut f = self.file.try_clone().ok();
|
||||||
|
if let Some(ref mut f) = f {
|
||||||
|
let mut buf = Vec::with_capacity(12);
|
||||||
|
buf.extend_from_slice(&(DRM_IOCTL_MODE_PAGE_FLIP as u64).to_le_bytes());
|
||||||
|
buf.extend_from_slice(&fb_id.to_le_bytes());
|
||||||
|
let _ = f.write_all(&buf);
|
||||||
|
}
|
||||||
|
self.current.store(next, Ordering::Relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(target_os = "redox"))]
|
||||||
|
mod drm_backend {
|
||||||
|
pub struct DrmOutput;
|
||||||
|
impl DrmOutput {
|
||||||
|
pub fn open() -> Option<Self> { None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn push_u32(buf: &mut Vec<u8>, value: u32) {
|
fn push_u32(buf: &mut Vec<u8>, value: u32) {
|
||||||
buf.extend_from_slice(&value.to_le_bytes());
|
buf.extend_from_slice(&value.to_le_bytes());
|
||||||
}
|
}
|
||||||
@@ -243,6 +389,8 @@ const OBJECT_TYPE_XDG_TOPLEVEL: u32 = 13;
|
|||||||
const OBJECT_TYPE_WL_SHM_POOL: u32 = 14;
|
const OBJECT_TYPE_WL_SHM_POOL: u32 = 14;
|
||||||
const OBJECT_TYPE_WL_POINTER: u32 = 15;
|
const OBJECT_TYPE_WL_POINTER: u32 = 15;
|
||||||
const OBJECT_TYPE_WL_KEYBOARD: u32 = 16;
|
const OBJECT_TYPE_WL_KEYBOARD: u32 = 16;
|
||||||
|
const OBJECT_TYPE_WL_DATA_DEVICE_MANAGER: u32 = 17;
|
||||||
|
const OBJECT_TYPE_WL_SUBCOMPOSITOR: u32 = 18;
|
||||||
|
|
||||||
struct Global {
|
struct Global {
|
||||||
name: u32,
|
name: u32,
|
||||||
@@ -292,6 +440,7 @@ pub struct Compositor {
|
|||||||
fb_height: u32,
|
fb_height: u32,
|
||||||
fb_stride: u32,
|
fb_stride: u32,
|
||||||
fb_data: Mutex<Vec<u8>>,
|
fb_data: Mutex<Vec<u8>>,
|
||||||
|
drm: Mutex<Option<drm_backend::DrmOutput>>,
|
||||||
clients: Mutex<HashMap<u32, ClientState>>,
|
clients: Mutex<HashMap<u32, ClientState>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,6 +451,7 @@ impl Compositor {
|
|||||||
fb_width: u32,
|
fb_width: u32,
|
||||||
fb_height: u32,
|
fb_height: u32,
|
||||||
fb_stride: u32,
|
fb_stride: u32,
|
||||||
|
drm: Mutex<Option<drm_backend::DrmOutput>>,
|
||||||
) -> std::io::Result<Self> {
|
) -> std::io::Result<Self> {
|
||||||
let _ = std::fs::remove_file(socket_path);
|
let _ = std::fs::remove_file(socket_path);
|
||||||
let listener = UnixListener::bind(socket_path)?;
|
let listener = UnixListener::bind(socket_path)?;
|
||||||
@@ -349,6 +499,16 @@ impl Compositor {
|
|||||||
interface: "xdg_wm_base".into(),
|
interface: "xdg_wm_base".into(),
|
||||||
version: 1,
|
version: 1,
|
||||||
},
|
},
|
||||||
|
Global {
|
||||||
|
name: 7,
|
||||||
|
interface: "wl_data_device_manager".into(),
|
||||||
|
version: 3,
|
||||||
|
},
|
||||||
|
Global {
|
||||||
|
name: 8,
|
||||||
|
interface: "wl_subcompositor".into(),
|
||||||
|
version: 1,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
@@ -360,6 +520,7 @@ impl Compositor {
|
|||||||
fb_height,
|
fb_height,
|
||||||
fb_stride,
|
fb_stride,
|
||||||
fb_data: Mutex::new(fb_data),
|
fb_data: Mutex::new(fb_data),
|
||||||
|
drm,
|
||||||
clients: Mutex::new(HashMap::new()),
|
clients: Mutex::new(HashMap::new()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -559,6 +720,8 @@ impl Compositor {
|
|||||||
"wl_seat" => OBJECT_TYPE_WL_SEAT,
|
"wl_seat" => OBJECT_TYPE_WL_SEAT,
|
||||||
"wl_output" => OBJECT_TYPE_WL_OUTPUT,
|
"wl_output" => OBJECT_TYPE_WL_OUTPUT,
|
||||||
"xdg_wm_base" => OBJECT_TYPE_XDG_WM_BASE,
|
"xdg_wm_base" => OBJECT_TYPE_XDG_WM_BASE,
|
||||||
|
"wl_data_device_manager" => OBJECT_TYPE_WL_DATA_DEVICE_MANAGER,
|
||||||
|
"wl_subcompositor" => OBJECT_TYPE_WL_SUBCOMPOSITOR,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
client.objects.insert(new_id, type_id);
|
client.objects.insert(new_id, type_id);
|
||||||
@@ -904,7 +1067,9 @@ impl Compositor {
|
|||||||
| OBJECT_TYPE_WL_BUFFER
|
| OBJECT_TYPE_WL_BUFFER
|
||||||
| OBJECT_TYPE_XDG_TOPLEVEL
|
| OBJECT_TYPE_XDG_TOPLEVEL
|
||||||
| OBJECT_TYPE_WL_POINTER
|
| OBJECT_TYPE_WL_POINTER
|
||||||
| OBJECT_TYPE_WL_KEYBOARD => {
|
| OBJECT_TYPE_WL_KEYBOARD
|
||||||
|
| OBJECT_TYPE_WL_DATA_DEVICE_MANAGER
|
||||||
|
| OBJECT_TYPE_WL_SUBCOMPOSITOR => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"redbear-compositor: unhandled opcode {} on object {}",
|
"redbear-compositor: unhandled opcode {} on object {}",
|
||||||
opcode, object_id
|
opcode, object_id
|
||||||
@@ -924,47 +1089,65 @@ impl Compositor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn composite_buffer(&self, pool: &mut ShmPool, buffer: &Buffer, surface: &Surface) {
|
fn composite_buffer(&self, pool: &mut ShmPool, buffer: &Buffer, surface: &Surface) {
|
||||||
let mut fb = self.fb_data.lock().unwrap();
|
|
||||||
let fb_stride = self.fb_stride as usize;
|
|
||||||
let byte_count = buffer.height as usize * buffer.stride as usize;
|
let byte_count = buffer.height as usize * buffer.stride as usize;
|
||||||
|
if buffer.offset as usize + byte_count > pool.size { return; }
|
||||||
if buffer.offset as usize + byte_count > pool.size {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut src = vec![0u8; byte_count];
|
let mut src = vec![0u8; byte_count];
|
||||||
if pool
|
if pool.file.seek(SeekFrom::Start(buffer.offset as u64)).is_err()
|
||||||
.file
|
|| pool.file.read_exact(&mut src).is_err() { return; }
|
||||||
.seek(SeekFrom::Start(buffer.offset as u64))
|
|
||||||
.is_err()
|
let fb_stride;
|
||||||
|| pool.file.read_exact(&mut src).is_err()
|
let fb_ptr: *mut u8;
|
||||||
{
|
// Try DRM first, fall back to fb_data Vec
|
||||||
return;
|
if let Ok(mut drm_guard) = self.drm.lock() {
|
||||||
|
if let Some(ref mut drm) = *drm_guard {
|
||||||
|
fb_stride = drm.stride as usize;
|
||||||
|
let idx = (drm.current.load(std::sync::atomic::Ordering::Relaxed) + 1) % drm.buffers.len().max(1);
|
||||||
|
fb_ptr = drm.buffers[idx].as_mut_ptr();
|
||||||
|
} else {
|
||||||
|
let mut fb = self.fb_data.lock().unwrap();
|
||||||
|
fb_stride = self.fb_stride as usize;
|
||||||
|
fb_ptr = fb.as_mut_ptr();
|
||||||
|
drop(fb); // release lock before unsafe block
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
let mut fb = self.fb_data.lock().unwrap();
|
||||||
|
fb_stride = self.fb_stride as usize;
|
||||||
|
fb_ptr = fb.as_mut_ptr();
|
||||||
|
drop(fb);
|
||||||
|
}
|
||||||
|
|
||||||
let dst_x = surface.x as usize;
|
let dst_x = surface.x as usize;
|
||||||
let dst_y = surface.y as usize;
|
let dst_y = surface.y as usize;
|
||||||
|
let fb_len = (self.fb_height as usize) * fb_stride;
|
||||||
|
unsafe {
|
||||||
for row in 0..buffer.height as usize {
|
for row in 0..buffer.height as usize {
|
||||||
let src_row = row * buffer.stride as usize;
|
let src_row = row * buffer.stride as usize;
|
||||||
let dst_row = (dst_y + row) * fb_stride + dst_x * 4;
|
let dst_row = (dst_y + row) * fb_stride + dst_x * 4;
|
||||||
|
if dst_row + buffer.width as usize * 4 <= fb_len
|
||||||
if dst_row + buffer.width as usize * 4 <= fb.len()
|
&& src_row + buffer.width as usize * 4 <= src.len() {
|
||||||
&& src_row + buffer.width as usize * 4 <= src.len()
|
|
||||||
{
|
|
||||||
for col in 0..buffer.width as usize {
|
for col in 0..buffer.width as usize {
|
||||||
let src_offset = src_row + col * 4;
|
let s = src_row + col * 4;
|
||||||
let dst_offset = dst_row + col * 4;
|
let d = dst_row + col * 4;
|
||||||
if dst_offset + 4 <= fb.len() && src_offset + 4 <= src.len() {
|
if d + 4 <= fb_len && s + 4 <= src.len() {
|
||||||
fb[dst_offset] = src[src_offset + 2];
|
*fb_ptr.add(d) = src[s + 2];
|
||||||
fb[dst_offset + 1] = src[src_offset + 1];
|
*fb_ptr.add(d + 1) = src[s + 1];
|
||||||
fb[dst_offset + 2] = src[src_offset];
|
*fb_ptr.add(d + 2) = src[s];
|
||||||
fb[dst_offset + 3] = 0xFF;
|
*fb_ptr.add(d + 3) = 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Page flip after compositing to DRM
|
||||||
|
if let Ok(mut drm_guard) = self.drm.lock() {
|
||||||
|
if let Some(ref drm) = *drm_guard {
|
||||||
|
drm.flip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn send_buffer_release(&self, stream: &mut UnixStream, buffer_id: u32) {
|
fn send_buffer_release(&self, stream: &mut UnixStream, buffer_id: u32) {
|
||||||
let mut msg = Vec::with_capacity(8);
|
let mut msg = Vec::with_capacity(8);
|
||||||
push_header(&mut msg, buffer_id, WL_BUFFER_RELEASE, 0);
|
push_header(&mut msg, buffer_id, WL_BUFFER_RELEASE, 0);
|
||||||
@@ -1065,30 +1248,30 @@ fn main() {
|
|||||||
std::env::var("XDG_RUNTIME_DIR").unwrap_or_else(|_| "/tmp/run/redbear-greeter".into());
|
std::env::var("XDG_RUNTIME_DIR").unwrap_or_else(|_| "/tmp/run/redbear-greeter".into());
|
||||||
let socket_path = format!("{}/{}", runtime_dir, wayland_display);
|
let socket_path = format!("{}/{}", runtime_dir, wayland_display);
|
||||||
|
|
||||||
// Read framebuffer parameters from environment (set by bootloader → vesad)
|
// Try DRM/KMS output first (hardware-accelerated via /scheme/drm/card0).
|
||||||
|
// Fall back to VESA framebuffer parameters from environment.
|
||||||
|
let drm = drm_backend::DrmOutput::open();
|
||||||
|
let (fb_width, fb_height, fb_stride, fb_phys) = if let Some(ref d) = drm {
|
||||||
|
eprintln!("redbear-compositor: using DRM/KMS output {}x{}", d.width, d.height);
|
||||||
|
(d.width, d.height, d.stride, 0)
|
||||||
|
} else {
|
||||||
let fb_width: u32 = std::env::var("FRAMEBUFFER_WIDTH")
|
let fb_width: u32 = std::env::var("FRAMEBUFFER_WIDTH")
|
||||||
.unwrap_or_else(|_| "1280".into())
|
.unwrap_or_else(|_| "1280".into()).parse().unwrap_or(1280);
|
||||||
.parse()
|
|
||||||
.unwrap_or(1280);
|
|
||||||
let fb_height: u32 = std::env::var("FRAMEBUFFER_HEIGHT")
|
let fb_height: u32 = std::env::var("FRAMEBUFFER_HEIGHT")
|
||||||
.unwrap_or_else(|_| "720".into())
|
.unwrap_or_else(|_| "720".into()).parse().unwrap_or(720);
|
||||||
.parse()
|
|
||||||
.unwrap_or(720);
|
|
||||||
let fb_stride: u32 = std::env::var("FRAMEBUFFER_STRIDE")
|
let fb_stride: u32 = std::env::var("FRAMEBUFFER_STRIDE")
|
||||||
.unwrap_or_else(|_| (fb_width * 4).to_string())
|
.unwrap_or_else(|_| (fb_width * 4).to_string()).parse().unwrap_or(fb_width * 4);
|
||||||
.parse()
|
|
||||||
.unwrap_or(fb_width * 4);
|
|
||||||
let fb_phys_str = std::env::var("FRAMEBUFFER_ADDR").unwrap_or_else(|_| "0x80000000".into());
|
let fb_phys_str = std::env::var("FRAMEBUFFER_ADDR").unwrap_or_else(|_| "0x80000000".into());
|
||||||
let fb_phys =
|
let fb_phys = usize::from_str_radix(fb_phys_str.trim_start_matches("0x"), 16).unwrap_or(0x80000000);
|
||||||
usize::from_str_radix(fb_phys_str.trim_start_matches("0x"), 16).unwrap_or(0x80000000);
|
|
||||||
|
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"redbear-compositor: fb {}x{} stride {} phys 0x{:X}",
|
"redbear-compositor: fb {}x{} stride {} phys 0x{:X}",
|
||||||
fb_width, fb_height, fb_stride, fb_phys
|
fb_width, fb_height, fb_stride, fb_phys
|
||||||
);
|
);
|
||||||
|
(fb_width, fb_height, fb_stride, fb_phys)
|
||||||
|
};
|
||||||
|
|
||||||
let socket_path_clone = socket_path.clone();
|
let socket_path_clone = socket_path.clone();
|
||||||
match Compositor::new(&socket_path, fb_phys, fb_width, fb_height, fb_stride) {
|
match Compositor::new(&socket_path, fb_phys, fb_width, fb_height, fb_stride, Mutex::new(drm)) {
|
||||||
Ok(mut compositor) => {
|
Ok(mut compositor) => {
|
||||||
if let Err(e) = compositor.run() {
|
if let Err(e) = compositor.run() {
|
||||||
eprintln!("redbear-compositor: {}", e);
|
eprintln!("redbear-compositor: {}", e);
|
||||||
|
|||||||
Reference in New Issue
Block a user