Take the console into graphics mode while drawing

This commit is contained in:
flamingcow
2026-07-25 21:30:37 -07:00
parent 892e855207
commit 12958ced56
+31
View File
@@ -12,6 +12,11 @@ const (
fbioGetVScreenInfo = 0x4600 fbioGetVScreenInfo = 0x4600
fbioBlank = 0x4611 fbioBlank = 0x4611
fbBlankUnblank = 0 fbBlankUnblank = 0
kdSetMode = 0x4b3a
kdText = 0x00
kdGraphics = 0x01
consolePath = "/dev/tty0"
) )
// The variable screen info is a flat run of 40 u32s, so it is read as an array // The variable screen info is a flat run of 40 u32s, so it is read as an array
@@ -28,6 +33,7 @@ const (
type framebuffer struct { type framebuffer struct {
file *os.File file *os.File
tty *os.File
mem []byte mem []byte
back []byte back []byte
w int w int
@@ -38,6 +44,22 @@ type framebuffer struct {
bShift uint bShift uint
} }
// The kernel console draws into the same framebuffer, including a blinking
// cursor and any keyboard echo, which fights every frame we write. Putting the
// active console into graphics mode stops it touching the framebuffer at all.
func takeConsole() (*os.File, error) {
tty, err := os.OpenFile(consolePath, os.O_RDWR, 0)
if err != nil {
return nil, err
}
if _, _, errno := unix.Syscall(unix.SYS_IOCTL, tty.Fd(),
kdSetMode, kdGraphics); errno != 0 {
tty.Close()
return nil, fmt.Errorf("console to graphics mode: %w", errno)
}
return tty, nil
}
func openFramebuffer(path string) (*framebuffer, error) { func openFramebuffer(path string) (*framebuffer, error) {
f, err := os.OpenFile(path, os.O_RDWR, 0) f, err := os.OpenFile(path, os.O_RDWR, 0)
if err != nil { if err != nil {
@@ -81,12 +103,21 @@ func openFramebuffer(path string) (*framebuffer, error) {
return nil, fmt.Errorf("mmap: %w", err) return nil, fmt.Errorf("mmap: %w", err)
} }
fb.back = make([]byte, fb.stride*fb.h) fb.back = make([]byte, fb.stride*fb.h)
fb.tty, err = takeConsole()
if err != nil {
unix.Munmap(fb.mem)
f.Close()
return nil, err
}
return fb, nil return fb, nil
} }
func (fb *framebuffer) close() { func (fb *framebuffer) close() {
fb.fill(rgb{}) fb.fill(rgb{})
fb.flush() fb.flush()
unix.Syscall(unix.SYS_IOCTL, fb.tty.Fd(), kdSetMode, kdText)
fb.tty.Close()
unix.Munmap(fb.mem) unix.Munmap(fb.mem)
fb.file.Close() fb.file.Close()
} }