Add basic character output for VGA graphics mode console (#649)

* Test output of colors for VGA graphics modes in examples/vga.c
* [metal] Character output in VGA graphics modes is mostly working
* [metal] Mention magic key to switch video mode, at bootup
This commit is contained in:
tkchia 2022-10-05 21:46:50 +08:00 committed by GitHub
parent b75a4654cf
commit edb8fef06c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 2059 additions and 324 deletions

View file

@ -1,5 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_VGA_VGA_INTERNAL_H_
#define COSMOPOLITAN_LIBC_VGA_VGA_INTERNAL_H_
#include "libc/runtime/mman.internal.h"
/** Preferred width of the video screen, in character units. */
#define VGA_PREFER_TTY_HEIGHT 30
@ -111,6 +112,31 @@ struct VgaTextCharCell {
uint8_t ch, attr;
};
typedef union {
uint32_t w;
struct {
uint8_t b, g, r, x;
} bgr;
} TtyBgrxColor;
typedef union {
uint32_t w;
struct {
uint8_t r, g, b, x;
} rgb;
} TtyRgbxColor;
typedef union {
uint16_t w;
} TtyBgr565Color;
typedef union {
uint16_t w;
} TtyBgr555Color;
typedef TtyBgrxColor TtyCanvasColor;
struct Tty;
struct Tty {
/**
* Cursor position. (y, x) = (0, 0) means the cursor is on the top left
@ -123,7 +149,12 @@ struct Tty {
unsigned short yp, xp;
/**
* Number of bytes (NOTE) occupied by each row of pixels, including any
* invisible "pixels".
* invisible "pixels", in the video frame buffer.
*/
unsigned short xsfb;
/**
* Number of bytes (NOTE) occupied by each row of pixels, including any
* invisible "pixels", in the canvas.
*/
unsigned short xs;
/** Type of video buffer (from mman::pc_video_type). */
@ -131,10 +162,35 @@ struct Tty {
uint32_t u8;
uint32_t n8;
uint32_t pr;
uint8_t fg, bg, chr_ht;
TtyCanvasColor fg, bg;
/**
* Height of each character in pixels. In text modes, this is used in
* setting the shape of the hardware cursor.
*/
uint8_t yc;
/**
* Width of each character in pixels. This is mostly useful only in
* graphics modes.
*/
uint8_t xc;
uint32_t conf;
unsigned short savey, savex;
struct VgaTextCharCell *ccs;
/** Actual video frame buffer as provided by the video card. */
char *fb;
/**
* Canvas to draw into. In text modes, this is simply the frame buffer
* itself. In graphics modes, this should be separate from the frame
* buffer, & possibly allocated from main memory; we must arrange to
* update the frame buffer from the canvas every now & then. In general
* the canvas's pixel format given by _TtyCanvasType() may be
* different from the frame buffer's.
*/
char *canvas;
/**
* Which portions of the canvas have been updated & should later be drawn
* to screen with tty->update().
*/
unsigned short updy1, updx1, updy2, updx2;
#ifdef VGA_USE_WCS
wchar_t *wcs;
#endif
@ -153,11 +209,28 @@ struct Tty {
size_t i;
char p[256];
} input;
void (*update)(struct Tty *);
void (*drawchar)(struct Tty *, size_t, size_t, wchar_t);
void (*eraselinecells)(struct Tty *, size_t, size_t, size_t);
void (*movelinecells)(struct Tty *, size_t, size_t, size_t, size_t, size_t);
};
void _StartTty(struct Tty *, unsigned short, unsigned short,
unsigned short, unsigned short, unsigned char,
void *, wchar_t *);
forceinline unsigned char _TtyCanvasType(struct Tty *tty) {
return tty->type == PC_VIDEO_TEXT ? PC_VIDEO_TEXT : PC_VIDEO_BGRX8888;
}
void _TtyBgrxUpdate(struct Tty *);
void _TtyRgbxUpdate(struct Tty *);
void _TtyBgr565Update(struct Tty *);
void _TtyBgr555Update(struct Tty *);
void _TtyGraphDrawChar(struct Tty *, size_t, size_t, wchar_t);
void _TtyGraphEraseLineCells(struct Tty *, size_t, size_t, size_t);
void _TtyGraphMoveLineCells(struct Tty *, size_t, size_t, size_t, size_t,
size_t);
void _StartTty(struct Tty *, unsigned char, unsigned short, unsigned short,
unsigned short, unsigned short, unsigned short,
unsigned char, unsigned char, void *, bool);
ssize_t _TtyRead(struct Tty *, void *, size_t);
ssize_t _TtyWrite(struct Tty *, const void *, size_t);
ssize_t _TtyWriteInput(struct Tty *, const void *, size_t);
@ -170,6 +243,7 @@ void _TtyEraseLines(struct Tty *, size_t, size_t);
void _TtySetY(struct Tty *, unsigned short);
void _TtySetX(struct Tty *, unsigned short);
extern const uint8_t _vga_font_default_direct[95][13];
extern struct Tty _vga_tty;
ssize_t sys_readv_vga(struct Fd *, const struct iovec *, int);