vtgl

terminal emulator implemented in OpenGL
git clone anongit@rnpnr.xyz:vtgl.git
Log | Files | Refs | Feed | LICENSE

util.h (8756B)


      1 /* See LICENSE for copyright details */
      2 #ifndef _UTIL_H_
      3 #define _UTIL_H_
      4 
      5 typedef union {
      6 	struct { u32 x, y; };
      7 	struct { u32 w, h; };
      8 	u32 E[2];
      9 } uv2;
     10 
     11 typedef __attribute__((aligned(16))) union {
     12 	struct { f32 x, y, z, w; };
     13 	struct { f32 r, g, b, a; };
     14 	f32 E[4];
     15 } v4;
     16 
     17 typedef struct { v2 pos, size; } Rect;
     18 
     19 typedef union {
     20 	/* NOTE: this assumes little endian */
     21 	struct { u8 a, b, g, r; };
     22 	u32 rgba;
     23 } Colour;
     24 
     25 enum variable_type {
     26 	VT_NULL,
     27 
     28 	VT_B32,
     29 	VT_U32,
     30 	VT_I32,
     31 	VT_F32,
     32 	VT_V4,
     33 	VT_S8,
     34 	VT_RANGE,
     35 	VT_SLL_VECTOR,
     36 
     37 	VT_GROUP,
     38 };
     39 
     40 struct Variable;
     41 
     42 typedef struct VariableLink {
     43 	struct VariableLink *prev;
     44 	struct VariableLink *next;
     45 	struct Variable     *var;
     46 } VariableLink;
     47 
     48 typedef struct {
     49 	VariableLink *next;
     50 	u32           count;
     51 } SLLVariableVector;
     52 
     53 #define SLLPush(sll, new) do {     \
     54 	(new)->next = (sll)->next; \
     55 	(sll)->next = (new);       \
     56 } while(0)
     57 
     58 #define SLLVariableVectorPush(a, sll, var) do {          \
     59 	VariableLink *vl = push_struct(a, VariableLink); \
     60 	SLLPush(sll, vl);                                \
     61 	(sll)->count++;                                  \
     62 	vl->var  = var;                                  \
     63 } while(0)
     64 
     65 #define DLLPushDown(head, new) do {  \
     66 	(new)->last  = (head);       \
     67 	(new)->next  = (head)->next; \
     68 	(head)->next = (new);        \
     69 } while(0)
     70 
     71 typedef struct Variable {
     72 	union {
     73 		b32 b32;
     74 		u32 u32;
     75 		i32 i32;
     76 		f32 f32;
     77 		s8  s8;
     78 		v4  v4;
     79 
     80 		Range range;
     81 
     82 		VariableLink      group;
     83 		SLLVariableVector vector;
     84 	};
     85 	enum variable_type type;
     86 } Variable;
     87 
     88 enum cell_attribute {
     89 	ATTR_NULL       = 0,
     90 	ATTR_BOLD       = 1 << 0,
     91 	ATTR_ITALIC     = 1 << 1,
     92 	ATTR_WIDE       = 1 << 2,
     93 	ATTR_WDUMMY     = 1 << 3, /* NOTE: used to skip cells when copying */
     94 	ATTR_FAINT      = 1 << 4,
     95 	ATTR_UNDERLINED = 1 << 5,
     96 	ATTR_BLINK      = 1 << 6,
     97 	ATTR_INVERSE    = 1 << 7,
     98 	ATTR_INVISIBLE  = 1 << 8,
     99 	ATTR_STRUCK     = 1 << 9,
    100 };
    101 #define ATTR_SHADER_MASK (ATTR_FAINT|ATTR_UNDERLINED|ATTR_BLINK|ATTR_INVERSE|ATTR_INVISIBLE|ATTR_STRUCK)
    102 #define ATTR_STYLE_MASK  (ATTR_BOLD|ATTR_ITALIC|ATTR_WIDE|ATTR_WDUMMY)
    103 
    104 #define SHADER_PACK_ATTR(a)  (((a) & ATTR_SHADER_MASK) >> 4)
    105 #define SHADER_PACK_FG(c, a) (((c) & 0xFFFFFF00) | SHADER_PACK_ATTR(a))
    106 #define SHADER_PACK_BG(c, a) (((c) & 0xFFFFFF00) | ((a) & ATTR_STYLE_MASK))
    107 
    108 typedef struct {
    109 	u32 cp;
    110 	u32 fg;
    111 	u32 bg;
    112 } Cell;
    113 
    114 enum cursor_state {
    115 	CURSOR_NORMAL    = 0 << 0,
    116 	CURSOR_WRAP_NEXT = 1 << 0,
    117 	CURSOR_ORIGIN    = 1 << 1,
    118 };
    119 
    120 typedef struct {
    121 	Colour fg, bg;
    122 	u32 attr;
    123 } CellStyle;
    124 
    125 typedef __attribute__((aligned(32))) struct {
    126 	CellStyle         style;
    127 	enum cursor_state state;
    128 	iv2               pos;
    129 
    130 	/* NOTE: 4 available charset slots and the selected charset slot to look in.
    131 	 * xterm stores this as part of the cursor so we do here as well. */
    132 	u32 charset_index;
    133 	u8  charsets[4];
    134 } Cursor;
    135 
    136 typedef Cell *Row;
    137 
    138 typedef struct {
    139 	Cell *cells;
    140 	Row  *rows;
    141 	MemoryBlock backing_store;
    142 } Framebuffer;
    143 
    144 typedef struct {
    145 	u8 *start, *end;
    146 	b32 has_unicode;
    147 	CellStyle cursor_state;
    148 } Line;
    149 
    150 typedef struct {
    151 	size cap;
    152 	size filled;
    153 	size widx;
    154 	Line *buf;
    155 } LineBuf;
    156 
    157 typedef struct {
    158 	RingBuf     log;
    159 	LineBuf     lines;
    160 	Framebuffer fb;
    161 } TermView;
    162 
    163 enum terminal_mode {
    164 	TM_ALTSCREEN = 1 << 0,
    165 	TM_REPLACE   = 1 << 1,
    166 	TM_AUTO_WRAP = 1 << 2,
    167 	TM_CRLF      = 1 << 3,
    168 	TM_UTF8      = 1 << 4,
    169 
    170 	TM_ALL_MASK = TM_UTF8|(TM_UTF8 - 1),
    171 };
    172 
    173 enum window_mode {
    174 	WM_APPCURSOR  = 1 << 0,
    175 	WM_HIDECURSOR = 1 << 1,
    176 	WM_BRACKPASTE = 1 << 2,
    177 	WM_8BIT       = 1 << 3,
    178 	WM_REVERSE    = 1 << 4,
    179 	WM_MOUSE_X10  = 1 << 5,
    180 	WM_MOUSE_BTN  = 1 << 6,
    181 	WM_MOUSE_TRK  = 1 << 7,
    182 	WM_MOUSE_SGR  = 1 << 8,
    183 
    184 	WM_MOUSE_MASK = WM_MOUSE_X10|WM_MOUSE_BTN|WM_MOUSE_TRK|WM_MOUSE_SGR,
    185 
    186 	WM_ALL_MASK = WM_MOUSE_SGR|(WM_MOUSE_SGR - 1),
    187 };
    188 
    189 #define MODE_STATE_ALL_MASK (ModeState){.term = TM_ALL_MASK, .win = WM_ALL_MASK}
    190 typedef struct {
    191 	enum terminal_mode term;
    192 	enum window_mode   win;
    193 } ModeState;
    194 
    195 #define SHADER_PMAT_LOC 0
    196 
    197 #define GL_POST_UNIFORMS \
    198 	X(param)         \
    199 	X(texslot)
    200 
    201 enum gl_flags {
    202 	RESIZE_RENDERER      = 1 << 0,
    203 	NEEDS_RESIZE         = 1 << 1,
    204 	NEEDS_REFILL         = 1 << 2,
    205 
    206 	DRAW_DEBUG_OVERLAY   = 1 << 30,
    207 };
    208 
    209 enum shader_stages {
    210 	SHADER_RENDER,
    211 	SHADER_RECTS,
    212 	SHADER_POST,
    213 	SHADER_COUNT
    214 };
    215 
    216 typedef struct {
    217 	iv2 cell_size;
    218 	iv2 term_size_in_cells;
    219 	iv2 term_size_in_pixels;
    220 
    221 	iv2 top_left_margin;
    222 	u32 margin_colour;
    223 
    224 	f32 blink_parameter;
    225 
    226 	f32 strike_min;
    227 	f32 strike_max;
    228 
    229 	f32 underline_min;
    230 	f32 underline_max;
    231 
    232 	u32 reverse_video_mask;
    233 
    234 	u32 _pad[1];
    235 } ShaderParameters;
    236 
    237 typedef struct {
    238 	iv2 window_size;
    239 
    240 	u32 vao, vbos[5];
    241 
    242 	u32 fb, fb_tex, fb_tex_unit;
    243 
    244 	u32 programs[SHADER_COUNT];
    245 	#define X(name) i32 name;
    246 	struct { GL_POST_UNIFORMS } post;
    247 	#undef X
    248 
    249 	_Alignas(16) ShaderParameters shader_parameters;
    250 	u32 render_shader_ubo;
    251 	u32 render_shader_ssbo;
    252 
    253 	iv2 glyph_bitmap_dim;
    254 	u32 glyph_bitmap_tex;
    255 
    256 	u32 flags;
    257 
    258 	u32 queued_render;
    259 } GLCtx;
    260 
    261 typedef struct {
    262 	u32 gpu_glyph;
    263 	u32 fg;
    264 	u32 bg;
    265 } RenderCell;
    266 
    267 /* TODO: try different sizes; largely depends on how many things we want to batch together */
    268 #define RENDER_PUSH_BUFFER_CAP 8192
    269 typedef __attribute__((aligned(64))) struct {
    270 	v2  positions[RENDER_PUSH_BUFFER_CAP];
    271 	v2  texture_coordinates[RENDER_PUSH_BUFFER_CAP];
    272 	v4  colours[RENDER_PUSH_BUFFER_CAP];
    273 	u32 count;
    274 } RenderPushBuffer;
    275 
    276 #define MIN_FONT_SIZE 8
    277 #define MAX_FONT_SIZE 128
    278 
    279 enum conversion_status { CR_FAILURE, CR_SUCCESS };
    280 struct conversion_result {
    281 	i32   status;
    282 	char *unparsed;
    283 	union { i32 i; f32 f; Colour colour;};
    284 };
    285 
    286 enum selection_states {
    287 	SS_NONE,
    288 	SS_CHAR,
    289 	SS_WORDS,
    290 };
    291 
    292 typedef struct {
    293 	Range range;
    294 	Range anchor;
    295 	enum  selection_states state;
    296 } Selection;
    297 
    298 typedef struct {
    299 	Row   *rows;
    300 	iv2    cursor;
    301 	iv2    next;
    302 	iv2    end;
    303 	u32    term_width;
    304 } SelectionIterator;
    305 
    306 enum face_style {
    307 	FS_NORMAL      = ATTR_NULL,
    308 	FS_BOLD        = ATTR_BOLD,
    309 	FS_ITALIC      = ATTR_ITALIC,
    310 	FS_BOLD_ITALIC = ATTR_BOLD|ATTR_ITALIC,
    311 	FS_COUNT,
    312 	FS_MASK        = FS_BOLD_ITALIC,
    313 };
    314 
    315 typedef struct {
    316 	i32 h, w;
    317 	i32 baseline;
    318 } FontInfo;
    319 
    320 typedef struct stbtt_fontinfo stbtt_fontinfo;
    321 typedef struct {
    322 	stbtt_fontinfo *font_info;
    323 	u8             *buf;
    324 	i32             bufsize;
    325 	f32             stbtt_scale;
    326 } Font;
    327 
    328 typedef Font FontFamily[FS_COUNT];
    329 
    330 typedef struct {
    331 	u32 cp;
    332 	u32 next_with_same_hash;
    333 	u32 prev;
    334 	u32 next;
    335 	u32 gpu_tile_index;
    336 	u8  tile_count;
    337 	u8  uploaded_to_gpu;
    338 	u16 advance;
    339 	i16 height;
    340 	i16 width;
    341 	i16 x0;
    342 	i16 y0;
    343 } CachedGlyph;
    344 
    345 typedef union {
    346 	struct {
    347 		u32 hit_count;
    348 		u32 miss_count;
    349 		u32 recycle_count;
    350 	};
    351 	u32 E[3];
    352 } GlyphCacheStats;
    353 
    354 typedef struct {
    355 	CachedGlyph     *glyphs;
    356 	u32             *hash_table;
    357 	u8              *occupied_tiles;
    358 	u32              cache_len;
    359 	GlyphCacheStats  stats;
    360 	u32              tiles_in_x;
    361 	u32              tiles_in_y;
    362 } GlyphCache;
    363 
    364 typedef struct {
    365 	FontFamily  *fonts;
    366 	u32          nfonts;
    367 	FontInfo     info;
    368 	GlyphCache   glyph_cache;
    369 } FontAtlas;
    370 
    371 typedef union {
    372 	i32   i;
    373 	f32   f;
    374 	void *v;
    375 } Arg;
    376 
    377 #define INTERACTION_MULTI_CLICK_TIME 0.5f
    378 
    379 enum interaction_types {
    380 	IS_NONE,
    381 	IS_NOP,
    382 	IS_SET,
    383 	IS_DRAG,
    384 
    385 	IS_AUTO,
    386 
    387 	IS_DEBUG,
    388 	IS_TERM,
    389 };
    390 
    391 typedef struct {
    392 	Variable var;
    393 	enum interaction_types type;
    394 } Interaction;
    395 
    396 typedef struct {
    397 	Interaction hot;
    398 	Interaction active;
    399 
    400 	u32 click_count;
    401 	f32 multi_click_t;
    402 
    403 	iv2 last_cell_report;
    404 } InteractionState;
    405 
    406 #define ESC_ARG_SIZ 6
    407 typedef struct {
    408 	s8 raw;
    409 	i32 argv[ESC_ARG_SIZ];
    410 	i32 argc;
    411 	u8 mode;
    412 	u8 priv;
    413 } CSI;
    414 
    415 typedef struct {
    416 	s8  raw;
    417 	s8  arg;
    418 	i32 cmd;
    419 } OSC;
    420 
    421 enum escape_mode {
    422 	EM_CSI = 1 << 0,
    423 	EM_STR = 1 << 1,
    424 };
    425 
    426 enum charsets {
    427 	CS_USA,
    428 	CS_GRAPHIC0,
    429 };
    430 
    431 typedef struct RenderCtx {
    432 	RenderPushBuffer *rpb;
    433 	GLCtx            *gl;
    434 	FontAtlas        *fa;
    435 	Arena             a;
    436 } RenderCtx;
    437 
    438 enum work_queue_entry_type {
    439 	WQ_RELOAD_SHADER,
    440 	WQ_RELOAD_ALL_SHADERS,
    441 };
    442 
    443 typedef struct {
    444 	void *ctx;
    445 	enum work_queue_entry_type type;
    446 } work_queue_entry;
    447 
    448 typedef struct Term {
    449 	GLCtx     gl;
    450 	FontAtlas fa;
    451 
    452 	Arena     arena_for_frame;
    453 	TempArena temp_arena;
    454 
    455 	work_queue_entry *work_queue_items;
    456 	u32               work_queue_capacity;
    457 	u32               work_queue;
    458 
    459 	InteractionState interaction;
    460 
    461 	Selection selection;
    462 
    463 	ModeState mode;
    464 	ModeState saved_mode;
    465 
    466 	Cursor    cursor;
    467 	Cursor    saved_cursors[2];
    468 
    469 	TermView  views[2];
    470 	i32       resize_lock;
    471 	i32       view_idx;
    472 	i32       scroll_offset;
    473 
    474 	size unprocessed_bytes;
    475 
    476 	iptr child;
    477 
    478 	iv2 size;
    479 	/* NOTE: scrolling region */
    480 	u32 top, bot;
    481 
    482 	CSI  csi;
    483 
    484 	enum escape_mode escape;
    485 
    486 	/* NOTE: this means we limit ourselves to 32 * 32 cells (1024). Even on a 4k sceen
    487 	 * this would mean that cells are ~4px wide which is unreadable */
    488 	u32 tabs[32];
    489 
    490 	Stream saved_title;
    491 	Stream error_stream;
    492 
    493 	PlatformAPI *platform;
    494 } Term;
    495 
    496 static f32 dt_for_frame;
    497 
    498 #endif /* _UTIL_H_ */