perf(explorer): per-frame window double buffering and present-aware FLUSH
This commit is contained in:
1 parent
6f856992da
commit
51287eb1a0
3 files changed
+40
-14
No files matched your search
@@ -854,6 +854,9 @@ class DeskServer:
|
||||
cap_px: int = w * content_h
|
||||
buf_off: uint32 = desk.desk_arena_alloc(self.shm, uint32(cap_px) * uint32(4))
|
||||
if buf_off == uint32(0): return -1
|
||||
# 第二块内容缓冲:应用始终画在非显示缓冲,FLUSH 后交换。
|
||||
buf2_off: uint32 = desk.desk_arena_alloc(self.shm, uint32(cap_px) * uint32(4))
|
||||
if buf2_off == uint32(0): buf2_off = buf_off
|
||||
s.used = 1
|
||||
s.pid = pid
|
||||
s.active = 1
|
||||
@@ -873,18 +876,22 @@ class DeskServer:
|
||||
s.fb_cap = uint32(cap_px)
|
||||
s.fb_w = uint32(w)
|
||||
s.fb_h = uint32(content_h)
|
||||
self.vis_off[i] = buf_off
|
||||
self.vis_off[i] = buf2_off
|
||||
self.vis_cap[i] = uint32(cap_px)
|
||||
self.vis_w[i] = w
|
||||
self.vis_h[i] = content_h
|
||||
self.spare_off[i] = uint32(0)
|
||||
self.spare_cap[i] = uint32(0)
|
||||
string.memset(&s.title, 0, desk.DESK_TITLE_MAX)
|
||||
# 像素缓冲先清成窗口底色,避免 app 还没画就露出垃圾
|
||||
# 两块缓冲都清成窗口底色,避免 app 还没画就露出垃圾
|
||||
buf: uint32* = uint32*(self.shm + uint64(buf_off))
|
||||
col: uint32 = self.rgb(uint32(30), uint32(30), uint32(50))
|
||||
for k in range(cap_px):
|
||||
buf[k] = col
|
||||
if buf2_off != buf_off:
|
||||
buf2: uint32* = uint32*(self.shm + uint64(buf2_off))
|
||||
for k2 in range(cap_px):
|
||||
buf2[k2] = col
|
||||
s.z_order = self.next_z
|
||||
self.next_z += 1
|
||||
self.focused = i
|
||||
@@ -1998,16 +2005,35 @@ class DeskServer:
|
||||
if self.hit_test(self.cx, self.cy) == win:
|
||||
self._mark_cursor_band()
|
||||
elif ty == uint32(desk.DESK_REQ_FLUSH):
|
||||
# 应用已经按 s.fb_w/fb_h 画完一帧:此刻才把"正在显示的内容"切到
|
||||
# 新缓冲。旧的 vis 缓冲留作下一次 resize 的备用。
|
||||
# present=0:PING/保活,不交换缓冲,避免显示未绘制的新缓冲。
|
||||
if m.a == 0:
|
||||
return
|
||||
old_off: uint32 = self.vis_off[win]
|
||||
if old_off != s.fb_off:
|
||||
self.spare_off[win] = old_off
|
||||
self.spare_cap[win] = self.vis_cap[win]
|
||||
self.vis_off[win] = s.fb_off
|
||||
self.vis_cap[win] = s.fb_cap
|
||||
self.vis_w[win] = int(s.fb_w)
|
||||
self.vis_h[win] = int(s.fb_h)
|
||||
old_cap: uint32 = self.vis_cap[win]
|
||||
need: int = int(s.fb_w) * int(s.fb_h)
|
||||
if s.fb_off != old_off:
|
||||
# 本帧画在新的 offscreen 缓冲里:切到它,旧 vis 作为下一帧目标。
|
||||
self.vis_off[win] = s.fb_off
|
||||
self.vis_cap[win] = s.fb_cap
|
||||
self.vis_w[win] = int(s.fb_w)
|
||||
self.vis_h[win] = int(s.fb_h)
|
||||
if old_off >= uint32(desk.DESK_OFF_ARENA) and int(old_cap) >= need:
|
||||
s.fb_off = old_off
|
||||
s.fb_cap = old_cap
|
||||
else:
|
||||
nw: uint32 = desk.desk_arena_alloc(self.shm, uint32(need * 4))
|
||||
if nw != uint32(0):
|
||||
s.fb_off = nw
|
||||
s.fb_cap = uint32(need)
|
||||
else:
|
||||
s.fb_off = old_off
|
||||
s.fb_cap = old_cap
|
||||
else:
|
||||
# 首帧或单缓冲回退:vis 已经是当前内容,为下一帧准备第二块。
|
||||
nw2: uint32 = desk.desk_arena_alloc(self.shm, uint32(need * 4))
|
||||
if nw2 != uint32(0):
|
||||
s.fb_off = nw2
|
||||
s.fb_cap = uint32(need)
|
||||
# 最小化窗口仍在后台绘制/FLUSH:不要置脏,否则合成器每帧都要重画背景。
|
||||
if s.minimized == 0:
|
||||
self.mark(s.uy, s.h)
|
||||
|
||||
+1
-1
@@ -2050,7 +2050,7 @@ virtual class Tk(Wm, Misc):
|
||||
need_redraw: int = 0
|
||||
etype: uint32 = evt.type
|
||||
if etype == window.EVENT_TYPE_PING:
|
||||
window.flush(self.win_id)
|
||||
window.flush(self.win_id, 0)
|
||||
elif etype == window.EVENT_TYPE_RESIZE:
|
||||
self.buf = window.get_winbuf(self.win_id)
|
||||
sz: int = window.get_win_size(self.win_id)
|
||||
|
||||
+2
-2
@@ -183,13 +183,13 @@ def get_win_size(win_id: int) -> int:
|
||||
if s.used == 0: return 0
|
||||
return (int(s.fb_w) << 16) | (int(s.fb_h) & 0xFFFF)
|
||||
|
||||
def flush(win_id: int):
|
||||
def flush(win_id: int, present: int = 1):
|
||||
# 槽位已被 explorer 回收(用户点了关闭):直接安全返回,绝不再发合成请求。
|
||||
if _connect() != 0: return
|
||||
if win_id < 0 or win_id >= desk.DESK_MAX_WIN: return
|
||||
s: desk.WinSlot* = _slot(win_id)
|
||||
if s.used == 0: return
|
||||
_send(uint32(desk.DESK_REQ_FLUSH), win_id, 0, 0, 0, 0, None)
|
||||
_send(uint32(desk.DESK_REQ_FLUSH), win_id, present, 0, 0, 0, None)
|
||||
|
||||
def text(win_id: int, x: int, y: int, color: uint32, s: const str) -> int:
|
||||
if _connect() != 0: return -1
|
||||
|
||||
Reference in new issue
Block a user