From d278e327b81235644bb10dd0ed57231911bb6498 Mon Sep 17 00:00:00 2001 From: tkchia Date: Sat, 1 Oct 2022 08:32:21 +0000 Subject: [PATCH] [metal] Start refactoring VGA console code, for graphics modes --- libc/vga/tty.c | 94 +++++++++++++++++++++++++++-------------- libc/vga/vga.internal.h | 20 ++++++++- libc/vga/writev-vga.c | 12 ++---- 3 files changed, 84 insertions(+), 42 deletions(-) diff --git a/libc/vga/tty.c b/libc/vga/tty.c index b15e027eb..23741ba99 100644 --- a/libc/vga/tty.c +++ b/libc/vga/tty.c @@ -240,7 +240,7 @@ static uint8_t TtyGetVgaAttr(struct Tty *tty) { return attr; } -void _TtyErase(struct Tty *tty, size_t dst, size_t n) { +static void TtyErase(struct Tty *tty, size_t dst, size_t n) { uint8_t attr = TtyGetVgaAttr(tty); size_t i; for (i = 0; i < n; ++i) @@ -248,11 +248,32 @@ void _TtyErase(struct Tty *tty, size_t dst, size_t n) { if (Wcs(tty)) wmemset(Wcs(tty) + dst, L' ', n); } -void _TtyMemmove(struct Tty *tty, size_t dst, size_t src, size_t n) { +void _TtyEraseLineCells(struct Tty *tty, size_t dsty, size_t dstx, size_t n) { + size_t xn = Xn(tty); + TtyErase(tty, dsty * xn + dstx, n); +} + +void _TtyEraseLines(struct Tty *tty, size_t dsty, size_t n) { + size_t xn = Xn(tty); + TtyErase(tty, dsty * xn, n * xn); +} + +static void TtyMemmove(struct Tty *tty, size_t dst, size_t src, size_t n) { memmove(tty->ccs + dst, tty->ccs + src, n * sizeof(struct VgaTextCharCell)); if (Wcs(tty)) wmemmove(Wcs(tty) + dst, Wcs(tty) + src, n); } +void _TtyMoveLineCells(struct Tty *tty, size_t dsty, size_t dstx, + size_t srcy, size_t srcx, size_t n) { + size_t xn = Xn(tty); + TtyMemmove(tty, dsty * xn + dstx, srcy * xn + srcx, n); +} + +void _TtyMoveLines(struct Tty *tty, size_t dsty, size_t srcy, size_t n) { + size_t xn = Xn(tty); + TtyMemmove(tty, dsty * xn, srcy * xn, n * xn); +} + void _TtyResetOutputMode(struct Tty *tty) { tty->pr = 0; tty->fg = DEFAULT_FG; @@ -272,7 +293,7 @@ void _TtyFullReset(struct Tty *tty) { _TtyResetOutputMode(tty); tty->y = 0; tty->x = 0; - _TtyErase(tty, 0, Yn(tty) * Xn(tty)); + _TtyEraseLines(tty, 0, Yn(tty)); } void _TtySetY(struct Tty *tty, unsigned short y) { @@ -286,13 +307,13 @@ void _TtySetX(struct Tty *tty, unsigned short x) { } static void TtyScroll(struct Tty *tty) { - _TtyMemmove(tty, 0, Xn(tty), Xn(tty) * (Yn(tty) - 1)); - _TtyErase(tty, Xn(tty) * (Yn(tty) - 1), Xn(tty)); + _TtyMoveLines(tty, 0, 1, Yn(tty) - 1); + _TtyEraseLines(tty, Yn(tty) - 1, 1); } static void TtyReverse(struct Tty *tty) { - _TtyMemmove(tty, Xn(tty), 0, Xn(tty) * (Yn(tty) - 1)); - _TtyErase(tty, 0, Xn(tty)); + _TtyMoveLines(tty, 1, 0, Yn(tty) - 1); + _TtyEraseLines(tty, 0, 1); } static void TtyIndex(struct Tty *tty) { @@ -464,15 +485,16 @@ static void TtyRestoreCursorPosition(struct Tty *tty) { static void TtyEraseDisplay(struct Tty *tty) { switch (TtyAtoi(tty->esc.s, NULL)) { case 0: - _TtyErase(tty, tty->y * Xn(tty) + tty->x, - Yn(tty) * Xn(tty) - (tty->y * Xn(tty) + tty->x)); + _TtyEraseLineCells(tty, tty->y, tty->x, Xn(tty) - tty->x); + _TtyEraseLines(tty, tty->y + 1, Yn(tty) - tty->y - 1); break; case 1: - _TtyErase(tty, 0, tty->y * Xn(tty) + tty->x); + _TtyEraseLines(tty, 0, tty->y); + _TtyEraseLineCells(tty, tty->y, 0, tty->x); break; case 2: case 3: - _TtyErase(tty, 0, Yn(tty) * Xn(tty)); + _TtyEraseLines(tty, 0, Yn(tty)); break; default: break; @@ -482,13 +504,13 @@ static void TtyEraseDisplay(struct Tty *tty) { static void TtyEraseLine(struct Tty *tty) { switch (TtyAtoi(tty->esc.s, NULL)) { case 0: - _TtyErase(tty, tty->y * Xn(tty) + tty->x, Xn(tty) - tty->x); + _TtyEraseLineCells(tty, tty->y, tty->x, Xn(tty) - tty->x); break; case 1: - _TtyErase(tty, tty->y * Xn(tty), tty->x); + _TtyEraseLineCells(tty, tty->y, 0, tty->x); break; case 2: - _TtyErase(tty, tty->y * Xn(tty), Xn(tty)); + _TtyEraseLines(tty, tty->y, 1); break; default: break; @@ -496,11 +518,23 @@ static void TtyEraseLine(struct Tty *tty) { } static void TtyEraseCells(struct Tty *tty) { - int i, n, x; - i = tty->y * Xn(tty) + tty->x; - n = Yn(tty) * Xn(tty); - x = min(max(TtyAtoi(tty->esc.s, NULL), 1), n - i); - _TtyErase(tty, i, x); + int yn, xn, yi, xi, n, left; + yn = Yn(tty); + xn = Xn(tty); + yi = tty->y; + xi = tty->x; + left = min(max(TtyAtoi(tty->esc.s, NULL), 1), yn * xn - (yi * xn + xi)); + while (left) { + if (left >= xn - xi) { + _TtyEraseLineCells(tty, yi, xi, xn - xi); + left -= xn - xi; + ++yi; + xi = 0; + } else { + _TtyEraseLineCells(tty, yi, xi, left); + left = 0; + } + } } static int TtyArg1(struct Tty *tty) { @@ -509,30 +543,28 @@ static int TtyArg1(struct Tty *tty) { static void TtyInsertCells(struct Tty *tty) { int n = min(Xn(tty) - tty->x, TtyArg1(tty)); - _TtyMemmove(tty, tty->y * Xn(tty) + tty->x + n, tty->y * Xn(tty) + tty->x, - Xn(tty) - (tty->x + n)); - _TtyErase(tty, tty->y * Xn(tty) + tty->x, n); + _TtyMoveLineCells(tty, tty->y, tty->x + n, tty->y, tty->x, + Xn(tty) - (tty->x + n)); + _TtyEraseLineCells(tty, tty->y, tty->x, n); } static void TtyInsertLines(struct Tty *tty) { int n = min(Yn(tty) - tty->y, TtyArg1(tty)); - _TtyMemmove(tty, (tty->y + n) * Xn(tty), tty->y * Xn(tty), - (Yn(tty) - tty->y - n) * Xn(tty)); - _TtyErase(tty, tty->y * Xn(tty), n * Xn(tty)); + _TtyMoveLines(tty, tty->y + n, tty->y, Yn(tty) - tty->y - n); + _TtyEraseLines(tty, tty->y, n); } static void TtyDeleteCells(struct Tty *tty) { int n = min(Xn(tty) - tty->x, TtyArg1(tty)); - _TtyMemmove(tty, tty->y * Xn(tty) + tty->x, tty->y * Xn(tty) + tty->x + n, - Xn(tty) - (tty->x + n)); - _TtyErase(tty, tty->y * Xn(tty) + tty->x, n); + _TtyMoveLineCells(tty, tty->y, tty->x, tty->y, tty->x + n, + Xn(tty) - (tty->x + n)); + _TtyEraseLineCells(tty, tty->y, tty->x, n); } static void TtyDeleteLines(struct Tty *tty) { int n = min(Yn(tty) - tty->y, TtyArg1(tty)); - _TtyMemmove(tty, tty->y * Xn(tty), (tty->y + n) * Xn(tty), - (Yn(tty) - tty->y - n) * Xn(tty)); - _TtyErase(tty, (tty->y + n) * Xn(tty), n * Xn(tty)); + _TtyMoveLines(tty, tty->y, tty->y + n, Yn(tty) - tty->y - n); + _TtyEraseLines(tty, tty->y + n, n); } static void TtyReportDeviceStatus(struct Tty *tty) { diff --git a/libc/vga/vga.internal.h b/libc/vga/vga.internal.h index 0312c75fe..b33806489 100644 --- a/libc/vga/vga.internal.h +++ b/libc/vga/vga.internal.h @@ -112,8 +112,22 @@ struct VgaTextCharCell { }; struct Tty { + /** + * Cursor position. (y, x) = (0, 0) means the cursor is on the top left + * character cell of the terminal. + */ unsigned short y, x; + /** Height and width of terminal, in character units. */ unsigned short yn, xn; + /** Height and width of terminal, in pixels (if in graphics video mode). */ + unsigned short yp, xp; + /** + * Number of bytes (NOTE) occupied by each row of pixels, including any + * invisible "pixels". + */ + unsigned short xs; + /** Type of video buffer (from mman::pc_video_type). */ + unsigned char type; uint32_t u8; uint32_t n8; uint32_t pr; @@ -149,8 +163,10 @@ ssize_t _TtyWrite(struct Tty *, const void *, size_t); ssize_t _TtyWriteInput(struct Tty *, const void *, size_t); void _TtyResetOutputMode(struct Tty *); void _TtyFullReset(struct Tty *); -void _TtyMemmove(struct Tty *, size_t, size_t, size_t); -void _TtyErase(struct Tty *, size_t, size_t); +void _TtyMoveLineCells(struct Tty *, size_t, size_t, size_t, size_t, size_t); +void _TtyMoveLines(struct Tty *, size_t, size_t, size_t); +void _TtyEraseLineCells(struct Tty *, size_t, size_t, size_t); +void _TtyEraseLines(struct Tty *, size_t, size_t); void _TtySetY(struct Tty *, unsigned short); void _TtySetX(struct Tty *, unsigned short); diff --git a/libc/vga/writev-vga.c b/libc/vga/writev-vga.c index 26824c2e9..710820bad 100644 --- a/libc/vga/writev-vga.c +++ b/libc/vga/writev-vga.c @@ -32,12 +32,6 @@ #include "libc/runtime/pc.internal.h" #include "libc/str/str.h" -#ifdef VGA_USE_WCS -static wchar_t vga_wcs[VGA_TTY_HEIGHT * VGA_TTY_WIDTH]; -#else -static wchar_t * const vga_wcs = NULL; -#endif - struct Tty _vga_tty; ssize_t sys_writev_vga(struct Fd *fd, const struct iovec *iov, int iovlen) { @@ -266,10 +260,10 @@ __attribute__((__constructor__)) static textstartup void _vga_init(void) { _vga_init_test(vid_buf, vid_type, stride); #endif /* - * Initialize our tty structure from the current screen contents, - * current cursor position, & character height. + * Initialize our tty structure from the current screen geometry, + * screen contents, cursor position, & character height. */ _StartTty(&_vga_tty, height, width, pos.row, pos.col, chr_ht, - vid_buf, vga_wcs); + vid_buf, NULL); } }