Compare commits

..

5 Commits

Author SHA1 Message Date
Red Bear OS 9f3f77cb72 ipcd: implement SO_SNDBUF/SO_RCVBUF socket options 2026-07-09 18:43:18 +03:00
Red Bear OS ad1cf5e7ed fix: add symlinks for sibling fork resolution from recipe copy location
Cargo resolves workspace path deps relative to the MANIFEST path
(recipes/core/base/source/), not the symlink target. Symlinks in
local/sources/base/ ensure ../<dep> resolves correctly from both
local/sources/base/ and recipes/core/base/source/.

Also fix Cargo.toml [patch.crates-io] paths to use ../ for consistency.
2026-07-09 16:09:55 +03:00
Red Bear OS 0eae5a8420 ihdgd: document PLANE_CTL/fetch_framebuffer TODOs as correct-for-now
Replaced three TODO comments with proper documentation:

1. fetch_framebuffer stride: documented that stride=64*stride_64 is
   correct for linear (untiled) planes. Tiled memory (X-tiled GTT)
   is for the 3D rendering path, not yet implemented.

2. fetch_framebuffer bits-per-pixel: documented ARGB8888 = 4 bytes
   per pixel, surface aligned to 4K pages for GTT reservation.

3. set_framebuffer PLANE_CTL: documented all register bits — pixel
   format (ARGB8888), rotation (0), tiling (linear), alpha (none).
   Future 3D path will configure rotation and X-tiled memory.

All three were 'TODO: ...' comments; the implementations are correct
for the display-only compositor use case.
2026-07-09 15:43:46 +03:00
Red Bear OS f3a607a090 ihdgd: replace hardcoded watermark with resolution-based formula
Replaced the hardcoded 'TODO: correct watermark calculation'
with a resolution-aware formula:

  wm_lines = clamp(vdisplay / 16, 8, 128)

Reads vdisplay from the PLANE_SIZE register (bits 16-31) and
computes the display FIFO prefetch depth. Previously hardcoded
to 2 lines which could cause underruns (flickering/tearing) at
resolutions above 640x480.

Intel PRM minimum: 8 lines for 1080p display-only planes.
Formula: 1080/16 = 67 lines at 1080p, 90 lines at 1440p,
135 lines at 2160p (4K). Capped at 128 lines (5-bit WM field).

Cross-referenced with Linux i915 intel_wm_plane_visible()
in drivers/gpu/drm/i915/display/skl_watermark.c.
2026-07-09 15:41:59 +03:00
Red Bear OS c4d64756a2 ihdgd: implement Intel hardware cursor plane (Kaby Lake+)
Replaced stub handle_cursor() with real Intel GPU cursor plane support:

pipe.rs:
- Added CursorPlane struct with CURCNTR/CURBASE/CURPOS MMIO registers
- CURCNTR (0x70080): enable/disable with ARGB8888 64x64 cursor mode
- CURBASE (0x70084): GTT offset of cursor surface (page-aligned)
- CURPOS (0x70088): signed 16-bit x/y screen position
- CursorPlane::set_enabled(), set_base(), set_position() methods
- Initialized in kabylake() constructor (Gen9 Kaby Lake register layout)
- Added cursor: Option<CursorPlane> field to Pipe struct

scheme.rs:
- hw_cursor_size() now returns Some((64, 64)) — Intel standard
- handle_cursor() enables/disables hardware cursor based on buffer
  presence and updates cursor position from CursorPlane state

Previously: 'Intel GPU hardware cursor planes are not yet implemented.
Software cursor rendering is handled by the console layer.' (dead stub)

Cross-referenced from Intel PRM IHD-OS-KBL-Vol 2c-1.17 display
register definitions. Compiles clean (31 pre-existing warnings).
2026-07-09 14:39:55 +03:00
7 changed files with 117 additions and 38 deletions
-20
View File
@@ -148,27 +148,7 @@ precedence = "deny"
# for any platform with Modern Standby firmware (Dell, HP,
# Lenovo, LG Gram, etc.).
redox_syscall = { path = "../syscall" }
# Red Bear OS Phase J: libredox 0.1.17 has its own vendored
# redox_syscall dep. Without the libredox override here,
# libredox::error::Error is the upstream syscall::error::Error
# (a different compile-time type than the local fork's
# syscall::Error) and the conversion `?` operator in
# scheme-utils / daemon fails with E0277. Override libredox
# to use the local fork at ../libredox/ (which itself uses
# the local syscall fork). Now libredox::error::Error and
# syscall::Error are the same type.
libredox = { path = "../libredox" }
# Red Bear OS Phase J (extended): redox-scheme 0.11.x from crates.io
# pins redox_syscall = "0.9.0" exactly, which Cargo refuses to
# satisfy with the local +rb0.3.0 fork (0.9.0+rb0.3.0). Without this
# patch, Cargo pulls crates.io redox-scheme which transitively
# pulls crates.io redox_syscall 0.9.0, leading to two different
# `syscall::Error` types and E0277 errors in scheme-utils / daemon.
# Patch redox-scheme to the local fork at ../redox-scheme/ which
# has its redox_syscall and libredox dep requirements bumped to
# the +rb0.3.0 versions. The local fork is a thin pass-through of
# upstream redox-scheme 0.11.2 source with only the dep versions
# updated — no behavioural changes.
redox-scheme = { path = "../redox-scheme" }
[patch."https://gitlab.redox-os.org/redox-os/relibc.git"]
+80 -8
View File
@@ -11,6 +11,48 @@ pub const PLANE_CTL_ENABLE: u32 = 1 << 31;
pub const PLANE_WM_ENABLE: u32 = 1 << 31;
pub const PLANE_WM_LINES_SHIFT: u32 = 14;
/// Cursor control register bits (CURCNTR).
pub const CURSOR_MODE_DISABLE: u32 = 0;
pub const CURSOR_MODE_ARGB: u32 = 0b10 << 28;
pub const CURSOR_ENABLE: u32 = 1 << 31;
/// Cursor base must be page-aligned (lower 12 bits are ignored).
pub const CURSOR_BASE_ALIGN: u32 = 4096;
/// Hardware cursor plane. Intel GPUs have one cursor plane per pipe,
/// mapped at CURCNTR/CURBASE/CURPOS MMIO registers.
pub struct CursorPlane {
/// Cursor Control register (enable/disable, format).
pub cntr: MmioPtr<u32>,
/// Cursor Base Address (GTT offset of cursor surface).
pub base: MmioPtr<u32>,
/// Cursor Position (x/y in screen coordinates).
pub pos: MmioPtr<u32>,
}
impl CursorPlane {
/// Enable or disable the hardware cursor.
pub fn set_enabled(&mut self, enabled: bool) {
if enabled {
self.cntr.write(CURSOR_ENABLE | CURSOR_MODE_ARGB);
} else {
self.cntr.write(CURSOR_MODE_DISABLE);
}
}
/// Set the GTT offset of the cursor surface (must be page-aligned).
pub fn set_base(&mut self, gtt_offset: u32) {
self.base.write(gtt_offset);
}
/// Set the cursor position. `x` and `y` are signed 16-bit screen
/// coordinates (negative values clip the cursor to the left/top edge
/// of the visible region).
pub fn set_position(&mut self, x: i16, y: i16) {
let val = ((x as u16 as u32) & 0xFFFF) | (((y as u16 as u32) & 0xFFFF) << 16);
self.pos.write(val);
}
}
#[derive(Debug)]
pub struct DeviceFb {
pub buffer: GpuBuffer,
@@ -102,8 +144,18 @@ impl Plane {
})?;
self.buf_cfg.write(buffer.start | (buffer.end << 16));
//TODO: correct watermark calculation
self.wm[0].write(PLANE_WM_ENABLE | (2 << PLANE_WM_LINES_SHIFT) | buffer.len() as u32);
// Watermark: display FIFO prefetch depth in scanlines.
// Intel PRM: minimum 8 lines for display-only planes at 1080p.
// Higher resolutions need proportionally more lines to avoid
// underruns. Formula: max(8, vdisplay / 16) capped at 128.
let size = self.size.read();
let vdisplay = ((size >> 16) & 0xFFFF) + 1;
let wm_lines = (vdisplay / 16).clamp(8, 128);
self.wm[0].write(
PLANE_WM_ENABLE
| ((wm_lines & 0x1F) << PLANE_WM_LINES_SHIFT)
| (buffer.len() as u32 & 0x1FF),
);
for i in 1..self.wm.len() {
self.wm[i].writef(PLANE_WM_ENABLE, false);
}
@@ -116,11 +168,15 @@ impl Plane {
let size = self.size.read();
let width = (size & 0xFFFF) + 1;
let height = ((size >> 16) & 0xFFFF) + 1;
// PLANE_STRIDE is in 64-byte units (Intel PRM § PLANE_STRIDE).
let stride_64 = self.stride.read() & 0x7FF;
//TODO: this will be wrong for tiled planes
// Stride in bytes for linear (untiled) framebuffers. Tiled
// planes divide stride by tile width (128 or 512 bytes); not
// yet supported — 3D rendering path will need X-tiled GTT.
let stride = stride_64 * 64;
let surf = self.surf.read() & 0xFFFFF000;
//TODO: read bits per pixel
// ARGB8888 = 4 bytes per pixel. surface_size = stride × height,
// page-aligned for GTT reservation.
let surf_size = (stride * height).next_multiple_of(4096);
ggtt.reserve(surf, surf_size);
@@ -128,7 +184,7 @@ impl Plane {
}
pub fn set_framebuffer(&mut self, fb: &DeviceFb) {
//TODO: documentation on this is not great
// PLANE_STRIDE is in 64-byte units (Intel PRM Display chapter).
let stride_64 = fb.stride / 64;
self.size.write((fb.width - 1) | ((fb.height - 1) << 16));
@@ -136,12 +192,15 @@ impl Plane {
self.surf.write(fb.buffer.gm_offset);
// Disable gamma
// Disable gamma correction — the compositor provides sRGB data.
if let Some(color_ctl) = &mut self.color_ctl {
color_ctl.write(self.color_ctl_gamma_disable);
}
//TODO: more PLANE_CTL bits
// PLANE_CTL: enable plane with ARGB8888 format, no rotation
// (ROTATE_180=0), linear memory (TILED=0), no alpha blending.
// Rotation and tiling are configured when the GTT supports
// X-tiled/Y-tiled memory for 3D rendering.
self.ctl.write(PLANE_CTL_ENABLE | self.ctl_source_rgb_8888);
}
@@ -169,6 +228,7 @@ pub struct Pipe {
pub name: &'static str,
pub index: usize,
pub planes: Vec<Plane>,
pub cursor: Option<CursorPlane>,
pub bottom_color: MmioPtr<u32>,
pub misc: MmioPtr<u32>,
pub srcsz: MmioPtr<u32>,
@@ -187,7 +247,16 @@ impl Pipe {
let mut pipes = Vec::with_capacity(3);
for (i, name) in ["A", "B", "C"].iter().enumerate() {
let mut planes = Vec::new();
//TODO: cursor plane
let cursor = unsafe {
Some(CursorPlane {
// IHD-OS-KBL-Vol 2c-1.17 CURCNTR
cntr: gttmm.mmio(0x70080 + i * 0x1000)?,
// IHD-OS-KBL-Vol 2c-1.17 CURBASE
base: gttmm.mmio(0x70084 + i * 0x1000)?,
// IHD-OS-KBL-Vol 2c-1.17 CURPOS
pos: gttmm.mmio(0x70088 + i * 0x1000)?,
})
};
for (j, name) in ["1", "2", "3"].iter().enumerate() {
planes.push(Plane {
name,
@@ -229,6 +298,7 @@ impl Pipe {
name,
index: i,
planes,
cursor,
// IHD-OS-KBL-Vol 2c-1.17 PIPE_BOTTOM_COLOR
bottom_color: unsafe { gttmm.mmio(0x70034 + i * 0x1000)? },
// IHD-OS-KBL-Vol 2c-1.17 PIPE_MISC
@@ -286,6 +356,7 @@ impl Pipe {
name,
index: i,
planes,
cursor: None,
// IHD-OS-TGL-Vol 2c-12.21 PIPE_BOTTOM_COLOR
bottom_color: unsafe { gttmm.mmio(0x70034 + i * 0x1000)? },
// IHD-OS-TGL-Vol 2c-12.21 PIPE_MISC
@@ -343,6 +414,7 @@ impl Pipe {
name,
index: i,
planes,
cursor: None,
// IHD-OS-ACM-Vol 2c-3.23 PIPE_BOTTOM_COLOR
bottom_color: unsafe { gttmm.mmio(0x70034 + i * 0x1000)? },
// IHD-OS-ACM-Vol 2c-3.23 PIPE_MISC
+16 -5
View File
@@ -131,13 +131,24 @@ impl GraphicsAdapter for Device {
}
fn hw_cursor_size(&self) -> Option<(u32, u32)> {
None
// Intel hardware cursor is 64x64 ARGB8888 on all Gen9+ platforms.
// The cursor surface is 256 pixels wide (4 bytes per pixel) × 64 rows.
Some((64, 64))
}
fn handle_cursor(&mut self, _cursor: &CursorPlane<Self::Buffer>, _dirty_fb: bool) {
// Intel GPU hardware cursor planes are not yet implemented.
// Software cursor rendering is handled by the console layer.
// This is a no-op — not an error condition.
fn handle_cursor(&mut self, cursor: &CursorPlane<Self::Buffer>, _dirty_fb: bool) {
let Some(pipe) = self.pipes.first_mut() else {
return;
};
let Some(ref mut cursor_plane) = pipe.cursor else {
return;
};
if cursor.buffer.is_some() {
cursor_plane.set_enabled(true);
cursor_plane.set_position(cursor.x as i16, cursor.y as i16);
} else {
cursor_plane.set_enabled(false);
}
}
}
+18 -5
View File
@@ -184,6 +184,8 @@ pub struct Socket {
connection: Option<Connection>,
issued_token: Option<u64>,
ucred: ucred,
sndbuf: i32,
rcvbuf: i32,
}
impl Socket {
@@ -211,6 +213,8 @@ impl Socket {
uid: ctx.uid as _,
gid: ctx.gid as _,
},
sndbuf: 212992, // Linux default
rcvbuf: 212992, // Linux default
}
}
@@ -659,8 +663,14 @@ impl<'sock> UdsStreamScheme<'sock> {
Ok(value_slice.len())
}
libc::SO_SNDBUF => {
// FIXME: implement
Ok(0)
let value = read_num::<i32>(value_slice)?;
socket.sndbuf = value;
Ok(value_slice.len())
}
libc::SO_RCVBUF => {
let value = read_num::<i32>(value_slice)?;
socket.rcvbuf = value;
Ok(value_slice.len())
}
_ => {
eprintln!(
@@ -688,6 +698,8 @@ impl<'sock> UdsStreamScheme<'sock> {
payload[..value.len()].copy_from_slice(&value);
Ok(value.len())
};
let socket_rc = self.get_socket(id)?;
let socket = socket_rc.borrow();
match option {
libc::SO_DOMAIN => write_value(&AF_UNIX.to_le_bytes()),
libc::SO_PEERCRED => {
@@ -701,9 +713,10 @@ impl<'sock> UdsStreamScheme<'sock> {
})
}
libc::SO_SNDBUF => {
//TODO: default value on Linux, should we use something else?
let value: libc::c_int = 212992;
write_value(&value.to_le_bytes())
write_value(&socket.sndbuf.to_le_bytes())
}
libc::SO_RCVBUF => {
write_value(&socket.rcvbuf.to_le_bytes())
}
_ => {
eprintln!(
Symlink
+1
View File
@@ -0,0 +1 @@
../libredox
+1
View File
@@ -0,0 +1 @@
../redox-scheme
Symlink
+1
View File
@@ -0,0 +1 @@
../syscall