diag(explorer,fb0): vblank 返回等待迭代数并打点;脏行合并为一段渲染

排查'仍闪烁':① FB_WAIT_VBLANK 改为返回等待消耗的迭代数(到上限 = 超时 = 当前没有 VGA 回扫信号),explorer 首次调用打印一次 —— 用来判定垂直回扫同步是否真的生效;② render() 原来按连续脏行分段、每段各渲染一次,同一帧的多次写屏会跨越多个扫描周期,现在把脏行合并成一段连续范围一次性渲染,缩小撕裂窗口。
This commit is contained in:
TermiNexus committed 2026-10-16 21:55:36 +08:00
1 parent ecabd59518
commit e1d31c3dc9
2 files changed
+25 -13

No files matched your search

+20 -9
View File
@@ -11,6 +11,8 @@ import viperlib
# 【诊断·临时】首个鼠标包已收到的标记(0 = 未收到)
_mouse_logged: int = 0
# 首次 vblank 等待的迭代数只打一次(诊断同步是否真的生效;到上限 = 超时)
_vblank_logged: int = 0
# ============================================================================
@@ -661,17 +663,26 @@ class DeskServer:
def render(self):
if self.dirty_any == 0: return
# 写屏前等垂直回扫(用户态不能 inb 0x3DA,由内核代等),避免撕裂
devfs.fb_wait_vblank(self.fb_fd)
y0: int = -1
y1: int = -1
y: int = 0
while y < self.fb_h:
if self.dirty[y] == 0:
y += 1
continue
y0: int = y
while y < self.fb_h and self.dirty[y] != 0:
y += 1
self.render_range(y0, y)
if self.dirty[y] != 0:
if y0 < 0: y0 = y
y1 = y + 1
y += 1
if y0 < 0:
self.clear_dirty()
return
# 写屏前等垂直回扫(用户态无 IO 权限,由内核代等);脏行合并成**一段**连续范围
# 一次性渲染 —— 分段渲染会让同一帧的多次写屏跨越多个扫描周期,撕裂更明显。
vw: int = devfs.fb_wait_vblank(self.fb_fd)
if _vblank_logged == 0:
_vblank_logged = 1
_vb: [96]char
viperlib.snprintf(&_vb, 96, "[explorer] vblank iters=%d\n", vw)
devfs.serial_puts(&_vb)
self.render_range(y0, y1)
self.clear_dirty()
# ---------------- 事件投递 ----------------
+5 -4
View File
@@ -522,12 +522,13 @@ virtual class framebuffer_device(devfs_file):
def ioctl(self, fd: int, request: int, arg: rawptr) -> int:
if request == FB_WAIT_VBLANK:
# 等进入垂直回扫期(0x3DA bit3)。带超时:当前若无 VGA 时序不至于死等。
# 等进入垂直回扫期(0x3DA bit3)。返回等待消耗的迭代数:到上限即超时
#(当前没有 VGA 回扫信号),调用方可据此判断同步是否真的生效。
t: int = 100000
while (asm.inb(0x3DA) & 0x08) != 0 and t > 0: t -= 1
t = 100000
while (asm.inb(0x3DA) & 0x08) == 0 and t > 0: t -= 1
return 0
t2: int = 100000
while (asm.inb(0x3DA) & 0x08) == 0 and t2 > 0: t2 -= 1
return 100000 - t2
if request != FB_GET_INFO or not arg:
return -1
info: FbInfo* = FbInfo*(uint64(arg))