diff --git a/Apps/Explorer/desk_server.vp b/Apps/Explorer/desk_server.vp index 5cfcfe1..eb0135a 100644 --- a/Apps/Explorer/desk_server.vp +++ b/Apps/Explorer/desk_server.vp @@ -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() # ---------------- 事件投递 ---------------- diff --git a/VKernel/Kernel/drivers/devfs/devfs.vp b/VKernel/Kernel/drivers/devfs/devfs.vp index 1daa36f..0a41bc8 100644 --- a/VKernel/Kernel/drivers/devfs/devfs.vp +++ b/VKernel/Kernel/drivers/devfs/devfs.vp @@ -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))