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_ */