util.h (9794B)
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 OSMemoryBlock 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 iz capacity; 152 iz filled; 153 iz count; 154 Line *data; 155 } LineBuffer; 156 157 typedef struct { 158 OSRingBuffer log; 159 LineBuffer 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 204 DRAW_DEBUG_OVERLAY = 1 << 30, 205 }; 206 207 /* X(enumerant, file_name) */ 208 #define FRAGMENT_SHADERS \ 209 X(RENDER, "frag_render") \ 210 X(RECTS, "frag_for_rects") \ 211 X(POST, "frag_post") 212 213 typedef enum { 214 #define X(en, fn) SID_ ##en, 215 FRAGMENT_SHADERS 216 #undef X 217 SID_LAST 218 } ShaderID; 219 220 typedef struct { 221 iv2 cell_size; 222 iv2 term_size_in_cells; 223 iv2 term_size_in_pixels; 224 225 iv2 top_left_margin; 226 u32 margin_colour; 227 228 f32 blink_parameter; 229 230 f32 strike_min; 231 f32 strike_max; 232 233 f32 underline_min; 234 f32 underline_max; 235 236 u32 reverse_video_mask; 237 238 u32 _pad[1]; 239 } ShaderParameters; 240 241 static_assert((sizeof(ShaderParameters) & 15) == 0, 242 "sizeof(ShaderParameters) must be a multiple of 16"); 243 244 typedef struct { 245 iv2 window_size; 246 247 u32 vao, vbos[5]; 248 249 u32 fb, fb_tex, fb_tex_unit; 250 251 ShaderID programs[SID_LAST]; 252 #define X(name) i32 name; 253 struct { GL_POST_UNIFORMS } post; 254 #undef X 255 256 _Alignas(16) ShaderParameters shader_parameters; 257 u32 render_shader_ubo; 258 u32 render_shader_ssbo; 259 260 iv2 glyph_bitmap_dim; 261 u32 glyph_bitmap_tex; 262 263 u32 flags; 264 265 u32 queued_render; 266 } GLCtx; 267 268 typedef struct { 269 u32 gpu_glyph; 270 u32 fg; 271 u32 bg; 272 } RenderCell; 273 274 /* TODO: try different sizes; largely depends on how many things we want to batch together */ 275 #define RENDER_PUSH_BUFFER_CAP 8192 276 typedef __attribute__((aligned(64))) struct { 277 v2 positions[RENDER_PUSH_BUFFER_CAP]; 278 v2 texture_coordinates[RENDER_PUSH_BUFFER_CAP]; 279 v4 colours[RENDER_PUSH_BUFFER_CAP]; 280 u32 count; 281 } RenderPushBuffer; 282 283 #define MIN_FONT_SIZE 8 284 #define MAX_FONT_SIZE 128 285 286 typedef enum { CR_FAILURE, CR_SUCCESS, CR_OUT_OF_RANGE } conversion_status; 287 struct conversion_result { 288 conversion_status status; 289 s8 unparsed; 290 union { i32 i; f32 f; Colour colour;}; 291 }; 292 293 enum selection_states { 294 SS_NONE, 295 SS_CHAR, 296 SS_WORDS, 297 }; 298 299 typedef struct { 300 Range range; 301 Range anchor; 302 enum selection_states state; 303 } Selection; 304 305 typedef struct { 306 Row *rows; 307 iv2 cursor; 308 iv2 next; 309 iv2 end; 310 i32 term_width; 311 } SelectionIterator; 312 313 enum face_style { 314 FS_NORMAL = ATTR_NULL, 315 FS_BOLD = ATTR_BOLD, 316 FS_ITALIC = ATTR_ITALIC, 317 FS_BOLD_ITALIC = ATTR_BOLD|ATTR_ITALIC, 318 FS_COUNT, 319 FS_MASK = FS_BOLD_ITALIC, 320 }; 321 322 typedef struct { 323 i32 h, w; 324 i32 baseline; 325 } FontInfo; 326 327 typedef struct stbtt_fontinfo stbtt_fontinfo; 328 typedef struct { 329 stbtt_fontinfo *font_info; 330 u8 *buf; 331 i32 bufsize; 332 f32 stbtt_scale; 333 } Font; 334 335 typedef Font FontFamily[FS_COUNT]; 336 337 typedef struct { 338 u32 cp; 339 u32 next_with_same_hash; 340 u32 prev; 341 u32 next; 342 u32 gpu_tile_index; 343 u8 tile_count; 344 u8 uploaded_to_gpu; 345 u16 advance; 346 i16 height; 347 i16 width; 348 i16 x0; 349 i16 y0; 350 } CachedGlyph; 351 352 typedef union { 353 struct { 354 u32 hit_count; 355 u32 miss_count; 356 u32 recycle_count; 357 }; 358 u32 E[3]; 359 } GlyphCacheStats; 360 361 typedef struct { 362 CachedGlyph *glyphs; 363 u32 *hash_table; 364 u8 *occupied_tiles; 365 u32 cache_len; 366 GlyphCacheStats stats; 367 i32 tiles_in_x; 368 i32 tiles_in_y; 369 } GlyphCache; 370 371 typedef struct { 372 FontFamily *fonts; 373 u32 nfonts; 374 FontInfo info; 375 GlyphCache glyph_cache; 376 } FontAtlas; 377 378 typedef union { 379 i32 i; 380 f32 f; 381 void *v; 382 } Arg; 383 384 #define INTERACTION_MULTI_CLICK_TIME 0.5f 385 386 enum interaction_types { 387 IS_NONE, 388 IS_NOP, 389 IS_SET, 390 IS_DRAG, 391 392 IS_AUTO, 393 394 IS_DEBUG, 395 IS_TERM, 396 }; 397 398 typedef struct { 399 Variable var; 400 enum interaction_types type; 401 } Interaction; 402 403 typedef struct { 404 Interaction hot; 405 Interaction active; 406 407 u32 click_count; 408 f32 multi_click_t; 409 410 iv2 last_cell_report; 411 } InteractionState; 412 413 #define ESC_ARG_SIZ 6 414 typedef struct { 415 s8 raw; 416 i32 argv[ESC_ARG_SIZ]; 417 i32 argc; 418 u8 mode; 419 u8 priv; 420 } CSI; 421 422 typedef struct { 423 s8 raw; 424 s8 arg; 425 i32 cmd; 426 } OSC; 427 428 enum escape_mode { 429 EM_CSI = 1 << 0, 430 EM_STR = 1 << 1, 431 }; 432 433 enum charsets { 434 CS_USA, 435 CS_GRAPHIC0, 436 }; 437 438 typedef struct ShaderReloadContext ShaderReloadContext; 439 440 typedef struct RenderCtx { 441 RenderPushBuffer *rpb; 442 GLCtx *gl; 443 FontAtlas *fa; 444 Arena a; 445 } RenderCtx; 446 447 typedef enum { 448 WQK_RELOAD_SHADER, 449 WQK_RELOAD_ALL_SHADERS, 450 } WorkQueueWorkKind; 451 452 typedef struct { 453 union { 454 void *generic; 455 ShaderReloadContext *shader_reload_context; 456 }; 457 WorkQueueWorkKind kind; 458 } WorkQueueWork; 459 460 typedef struct { 461 union { 462 u64 queue; 463 struct {u32 widx, ridx;}; 464 }; 465 WorkQueueWork items[1 << 6]; 466 } WorkQueue; 467 468 struct ShaderReloadContext { 469 WorkQueue *work_queue; 470 s8 path; 471 s8 label; 472 ShaderID shader; 473 }; 474 475 typedef struct { 476 GLCtx gl; 477 FontAtlas fa; 478 WorkQueue work_queue; 479 480 Arena arena; 481 482 /* TODO(rnp): cleanup */ 483 TerminalInput *input; 484 485 iptr window; 486 iv2 monitor_size; 487 488 /* TODO(rnp): cleanup */ 489 Stream error_stream; 490 491 i32 *sync; 492 493 ShaderReloadContext shader_reload_contexts[SID_LAST]; 494 495 b32 running; 496 } RenderThreadContext; 497 498 typedef enum { 499 TS_NEEDS_RESIZE = 1 << 0, 500 TS_NEEDS_REFILL = 1 << 1, 501 } TerminalState; 502 503 typedef struct { 504 Arena arena_for_frame; 505 TempArena temp_arena; 506 507 InteractionState interaction; 508 509 Selection selection; 510 511 TerminalState state; 512 513 ModeState mode; 514 ModeState saved_mode; 515 516 Cursor cursor; 517 Cursor saved_cursors[2]; 518 519 TermView views[2]; 520 i32 resize_lock; 521 i32 view_idx; 522 i32 scroll_offset; 523 524 iz unprocessed_bytes; 525 526 iptr child; 527 528 iv2 size; 529 /* NOTE: scrolling region */ 530 i32 top, bot; 531 532 CSI csi; 533 534 enum escape_mode escape; 535 536 /* NOTE: this means we limit ourselves to 32 * 32 cells (1024). Even on a 4k sceen 537 * this would mean that cells are ~4px wide which is unreadable */ 538 u32 tabs[32]; 539 540 Stream saved_title; 541 Stream error_stream; 542 543 RenderThreadContext render_thread; 544 545 OS *os; 546 } Term; 547 548 #define LABEL_GL_OBJECT(type, id, s) {s8 _s = (s); glObjectLabel(type, id, _s.len, (c8 *)_s.data);} 549 550 global f32 dt_for_frame; 551 552 #endif /* _UTIL_H_ */