fix: GPU display at correct resolution, clean up diagnostics
- Add GET_DISPLAY_INFO command to query QEMU's preferred resolution (was hardcoded 640x480, QEMU wanted 1280x800) - Allocate framebuffer matching actual display dimensions - Remove debug diagnostic output from display server and snake
This commit is contained in:
@@ -13,10 +13,8 @@ const VQUEUE_VA: usize = 0x21000;
|
|||||||
const CMDBUF_VA: usize = 0x23000;
|
const CMDBUF_VA: usize = 0x23000;
|
||||||
const PHYSINFO_VA: usize = 0x24000;
|
const PHYSINFO_VA: usize = 0x24000;
|
||||||
const FB_VA: usize = 0x100000;
|
const FB_VA: usize = 0x100000;
|
||||||
const FB_WIDTH: Dimension = Dimension::new(640);
|
const DEFAULT_WIDTH: Dimension = Dimension::new(640);
|
||||||
const FB_HEIGHT: Dimension = Dimension::new(480);
|
const DEFAULT_HEIGHT: Dimension = Dimension::new(480);
|
||||||
const FB_BPP: usize = 4;
|
|
||||||
const FB_PAGES: usize = (FB_WIDTH.raw() as usize * FB_HEIGHT.raw() as usize * FB_BPP + 4095) / 4096;
|
|
||||||
|
|
||||||
pub fn configure(uart: &Uart, display_pid: ProcessId) {
|
pub fn configure(uart: &Uart, display_pid: ProcessId) {
|
||||||
let gpu = match VirtioGpu::probe() {
|
let gpu = match VirtioGpu::probe() {
|
||||||
@@ -38,8 +36,36 @@ pub fn configure(uart: &Uart, display_pid: ProcessId) {
|
|||||||
let cmd_phys = mmu::allocator::alloc_zeroed_page();
|
let cmd_phys = mmu::allocator::alloc_zeroed_page();
|
||||||
map_page(pt, CMDBUF_VA, cmd_phys);
|
map_page(pt, CMDBUF_VA, cmd_phys);
|
||||||
|
|
||||||
let fb_phys = alloc_contiguous(FB_PAGES);
|
gpu.init_device(vq_phys);
|
||||||
map_range(pt, FB_VA, fb_phys, FB_PAGES);
|
|
||||||
|
let queue = hw_virtio::queue::VirtioQueue::new(
|
||||||
|
hw_virtio::queue::QueueAddrs::from_base(vq_phys),
|
||||||
|
);
|
||||||
|
let dma = hw_virtio::gpu::GpuDmaAddrs {
|
||||||
|
cmd_pa: types::address::PhysicalAddress::from_raw(cmd_phys),
|
||||||
|
cmd_va: types::address::VirtualAddress::from_raw(cmd_phys),
|
||||||
|
resp_pa: types::address::PhysicalAddress::from_raw(cmd_phys + 512),
|
||||||
|
};
|
||||||
|
use hw_virtio::mmio::MmioAccess;
|
||||||
|
|
||||||
|
let (width, height) = match hw_virtio::gpu::get_display_info(gpu.mmio(), &queue, &dma) {
|
||||||
|
Some((w, h)) => {
|
||||||
|
uart.write_str("k-os: GPU display: ");
|
||||||
|
uart.write_dec(w as usize);
|
||||||
|
uart.put_char(b'x');
|
||||||
|
uart.write_dec(h as usize);
|
||||||
|
uart.put_char(b'\n');
|
||||||
|
(Dimension::new(w as u16), Dimension::new(h as u16))
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
uart.write_str("k-os: GPU display: using default 640x480\n");
|
||||||
|
(DEFAULT_WIDTH, DEFAULT_HEIGHT)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let fb_pages = (width.raw() as usize * height.raw() as usize * 4 + 4095) / 4096;
|
||||||
|
let fb_phys = alloc_contiguous(fb_pages);
|
||||||
|
map_range(pt, FB_VA, fb_phys, fb_pages);
|
||||||
|
|
||||||
let info_phys = mmu::allocator::alloc_zeroed_page();
|
let info_phys = mmu::allocator::alloc_zeroed_page();
|
||||||
map_page(pt, PHYSINFO_VA, info_phys);
|
map_page(pt, PHYSINFO_VA, info_phys);
|
||||||
@@ -48,12 +74,11 @@ pub fn configure(uart: &Uart, display_pid: ProcessId) {
|
|||||||
core::ptr::write_volatile(info, cmd_phys as u64);
|
core::ptr::write_volatile(info, cmd_phys as u64);
|
||||||
core::ptr::write_volatile(info.add(1), (cmd_phys + 512) as u64);
|
core::ptr::write_volatile(info.add(1), (cmd_phys + 512) as u64);
|
||||||
core::ptr::write_volatile(info.add(2), fb_phys as u64);
|
core::ptr::write_volatile(info.add(2), fb_phys as u64);
|
||||||
core::ptr::write_volatile(info.add(3), FB_WIDTH.raw() as u64);
|
core::ptr::write_volatile(info.add(3), width.raw() as u64);
|
||||||
core::ptr::write_volatile(info.add(4), FB_HEIGHT.raw() as u64);
|
core::ptr::write_volatile(info.add(4), height.raw() as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu.init_device(vq_phys);
|
if gpu.setup_framebuffer(cmd_phys, vq_phys, fb_phys, width, height) {
|
||||||
if gpu.setup_framebuffer(cmd_phys, vq_phys, fb_phys, FB_WIDTH, FB_HEIGHT) {
|
|
||||||
uart.write_str("k-os: VirtIO GPU configured\n");
|
uart.write_str("k-os: VirtIO GPU configured\n");
|
||||||
} else {
|
} else {
|
||||||
uart.write_str("k-os: VirtIO GPU setup failed (display will be headless)\n");
|
uart.write_str("k-os: VirtIO GPU setup failed (display will be headless)\n");
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use display_server::protocol::DisplayRequest;
|
|||||||
|
|
||||||
const INPUT_EP: CapSlot = CapSlot::const_new(0);
|
const INPUT_EP: CapSlot = CapSlot::const_new(0);
|
||||||
const DISPLAY_EP: CapSlot = CapSlot::const_new(1);
|
const DISPLAY_EP: CapSlot = CapSlot::const_new(1);
|
||||||
const TICK_DELAY: u64 = 2_000_000;
|
const TICK_DELAY: u64 = 5_000_000;
|
||||||
const MAX_RENDER_CMDS: usize = 140;
|
const MAX_RENDER_CMDS: usize = 140;
|
||||||
|
|
||||||
fn display_send(req: &DisplayRequest) {
|
fn display_send(req: &DisplayRequest) {
|
||||||
@@ -50,20 +50,17 @@ extern "C" fn main() {
|
|||||||
}
|
}
|
||||||
flush();
|
flush();
|
||||||
|
|
||||||
wait_tick();
|
|
||||||
handle_input(&mut snake);
|
|
||||||
snake.tick();
|
|
||||||
|
|
||||||
if snake.state() == GameState::GameOver {
|
if snake.state() == GameState::GameOver {
|
||||||
let gw = renderer::grid_pixel_width();
|
let gw = renderer::grid_pixel_width();
|
||||||
let gh = renderer::grid_pixel_height();
|
let gh = renderer::grid_pixel_height();
|
||||||
draw_rect(gw / 2 - 60, gh / 2 - 12, 120, 24, 0xFF800000);
|
draw_rect(gw / 2 - 60, gh / 2 - 12, 120, 24, 0xFFCC0000);
|
||||||
flush();
|
flush();
|
||||||
|
loop { syscall::yield_now(); }
|
||||||
let end = Ticks::from_raw(syscall::get_time().raw() + 50_000_000);
|
|
||||||
while syscall::get_time().raw() < end.raw() { syscall::yield_now(); }
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wait_tick();
|
||||||
|
handle_input(&mut snake);
|
||||||
|
snake.tick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,24 @@ fn write_cmd_header(cmd_va: VirtualAddress, cmd_type: u32) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_display_info(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs) -> Option<(u32, u32)> {
|
||||||
|
write_cmd_header(dma.cmd_va, 0x0100);
|
||||||
|
let descs = [
|
||||||
|
Descriptor { addr: dma.cmd_pa.raw() as u64, len: 24, writable: false },
|
||||||
|
Descriptor { addr: dma.resp_pa.raw() as u64, len: 408, writable: true },
|
||||||
|
];
|
||||||
|
if !queue.submit(mmio, &descs) { return None; }
|
||||||
|
unsafe {
|
||||||
|
let resp = dma.resp_pa.raw() as usize;
|
||||||
|
let resp_va = dma.cmd_va.raw() + 512;
|
||||||
|
let resp_type = core::ptr::read_volatile(resp_va as *const u32);
|
||||||
|
if resp_type != 0x1101 { return None; }
|
||||||
|
let w = core::ptr::read_volatile((resp_va + 24 + 8) as *const u32);
|
||||||
|
let h = core::ptr::read_volatile((resp_va + 24 + 12) as *const u32);
|
||||||
|
if w > 0 && h > 0 { Some((w, h)) } else { None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn submit_cmd(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, cmd_len: u32) -> bool {
|
fn submit_cmd(mmio: &impl MmioAccess, queue: &VirtioQueue, dma: &GpuDmaAddrs, cmd_len: u32) -> bool {
|
||||||
let descs = [
|
let descs = [
|
||||||
Descriptor { addr: dma.cmd_pa.raw() as u64, len: cmd_len, writable: false },
|
Descriptor { addr: dma.cmd_pa.raw() as u64, len: cmd_len, writable: false },
|
||||||
|
|||||||
Reference in New Issue
Block a user