From 85db87a1213af843180f90b87a4f2217704e5f0f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 11 Oct 2021 11:10:19 +0530 Subject: [PATCH] A shader to draw a single seven segment number over a kitty window --- kitty/fast_data_types.pyi | 2 ++ kitty/seven_segment_fragment.glsl | 39 +++++++++++++++++++++++++++++++ kitty/shaders.c | 34 +++++++++++++++++++++++++-- kitty/utils.py | 9 +++---- kitty/window.py | 16 +++++++------ 5 files changed, 87 insertions(+), 13 deletions(-) create mode 100644 kitty/seven_segment_fragment.glsl diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index bce610f35..41c384b5b 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -263,6 +263,7 @@ SCROLL_LINE: int SCROLL_PAGE: int STRIKETHROUGH: int TINT_PROGRAM: int +SEVEN_SEGMENT_PROGRAM: int FC_MONO: int = 100 FC_DUAL: int FC_WEIGHT_REGULAR: int @@ -1239,5 +1240,6 @@ def get_os_window_size(os_window_id: int) -> Optional[OSWindowSize]: def get_all_processes() -> Tuple[int, ...]: pass + def num_users() -> int: pass diff --git a/kitty/seven_segment_fragment.glsl b/kitty/seven_segment_fragment.glsl new file mode 100644 index 000000000..0b2d1f0f5 --- /dev/null +++ b/kitty/seven_segment_fragment.glsl @@ -0,0 +1,39 @@ +#version GLSL_VERSION +uniform vec4 area_bounds; +uniform vec4 digit_color; +uniform int digit; +layout(origin_upper_left) in vec4 gl_FragCoord; + +const float PI = 3.1415926535897932384626433832795; +const int s_map[] = int[10](182, 150, 78, 47, 104, 85, 16, 212, 15, 142); + +mat2 rotate2D(in float a) { + return mat2(cos(a), sin(a), -sin(a), cos(a)); +} + +float draw_number(int num, vec2 p) { + // return 1 if this position should be colored and 0 if not + int s = s_map[max(0, min(num, 9))]; + float scale = 0.3; + float n = fract(sin(dot(ceil(p * rotate2D(PI / 4.) / sqrt(2.) / scale + 0.5 + float(s)), vec2(3., 5.))) * 50.); + + p.y = abs(p.y); + p.y -= scale; + p = abs(p); + p = vec2(max(p.x, p.y), min(p.x, p.y)); + p.x -= scale; + p.x = abs(p.x); + float d = max(p.x + p.y - scale * 0.667, p.x); + return step(d, scale * 0.267) * step(n, 0.5); +} + +out vec4 color; + +void main() { + float left = area_bounds[0], top = area_bounds[1]; + vec2 resolution = vec2(area_bounds[2], area_bounds[3]); + vec2 shifted_frag_pos = vec2(gl_FragCoord.x - left, gl_FragCoord.y - top); + vec2 pos = (shifted_frag_pos * 2 - resolution) / min(resolution.x, resolution.y); + pos.y *= -1; + color = digit_color * draw_number(digit, pos); +} diff --git a/kitty/shaders.c b/kitty/shaders.c index a47330977..187d8664f 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -9,7 +9,7 @@ #include "gl.h" #include -enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, BLIT_PROGRAM, BGIMAGE_PROGRAM, TINT_PROGRAM, NUM_PROGRAMS }; +enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, BLIT_PROGRAM, BGIMAGE_PROGRAM, TINT_PROGRAM, SEVEN_SEGMENT_PROGRAM, NUM_PROGRAMS }; enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT, BGIMAGE_UNIT }; // Sprites {{{ @@ -172,6 +172,10 @@ typedef struct { GLint tint_color_location, edges_location; } TintProgramLayout; static TintProgramLayout tint_program_layout = {0}; +typedef struct { + GLint edges_location, area_bounds_location, digit_color_location, digit_location; +} SevenSegmentProgramLayout; +static SevenSegmentProgramLayout seven_segment_program_layout = {0}; static void init_cell_program(void) { @@ -197,6 +201,10 @@ init_cell_program(void) { bgimage_program_layout.premult_location = get_uniform_location(BGIMAGE_PROGRAM, "premult"); tint_program_layout.tint_color_location = get_uniform_location(TINT_PROGRAM, "tint_color"); tint_program_layout.edges_location = get_uniform_location(TINT_PROGRAM, "edges"); + seven_segment_program_layout.edges_location = get_uniform_location(SEVEN_SEGMENT_PROGRAM, "edges"); + seven_segment_program_layout.area_bounds_location = get_uniform_location(SEVEN_SEGMENT_PROGRAM, "area_bounds"); + seven_segment_program_layout.digit_color_location = get_uniform_location(SEVEN_SEGMENT_PROGRAM, "digit_color"); + seven_segment_program_layout.digit_location = get_uniform_location(SEVEN_SEGMENT_PROGRAM, "digit"); } #define CELL_BUFFERS enum { cell_data_buffer, selection_buffer, uniform_buffer }; @@ -458,6 +466,26 @@ draw_tint(bool premult, Screen *screen, GLfloat xstart, GLfloat ystart, GLfloat glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } +static void +draw_window_number(OSWindow *os_window, Screen *screen, GLfloat xstart, GLfloat ystart, GLfloat width, GLfloat height) { + glEnable(GL_BLEND); + glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); // BLEND_PREMULT + bind_program(SEVEN_SEGMENT_PROGRAM); + GLfloat left = os_window->viewport_width * (xstart + 1.f) / 2.f; + GLfloat right = left + os_window->viewport_width * width / 2.f; + GLfloat top = os_window->viewport_height * (1.f - ystart) / 2.f; + GLfloat bottom = os_window->viewport_height * (1.f + height - ystart) / 2.f; + glUniform4f(seven_segment_program_layout.edges_location, xstart, ystart - height, xstart + width, ystart); + glUniform4f(seven_segment_program_layout.area_bounds_location, left, top, right - left, bottom - top); + color_type digit_color = colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.highlight_bg, screen->color_profile->configured.highlight_bg); +#define C(shift) ((((GLfloat)((digit_color >> shift) & 0xFF)) / 255.0f)) + glUniform4f(seven_segment_program_layout.digit_color_location, C(16), C(8), C(0), 1.); +#undef C + glUniform1i(seven_segment_program_layout.digit_location, 8); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisable(GL_BLEND); +} + static void draw_visual_bell_flash(GLfloat intensity, GLfloat xstart, GLfloat ystart, GLfloat w, GLfloat h, Screen *screen) { glEnable(GL_BLEND); @@ -706,6 +734,8 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL GLfloat intensity = get_visual_bell_intensity(screen); if (intensity > 0.0f) draw_visual_bell_flash(intensity, xstart, ystart, w, h, screen); } + + if (false) draw_window_number(os_window, screen, xstart, ystart, w, h); } // }}} @@ -867,7 +897,7 @@ static PyMethodDef module_methods[] = { bool init_shaders(PyObject *module) { #define C(x) if (PyModule_AddIntConstant(module, #x, x) != 0) { PyErr_NoMemory(); return false; } - C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM); C(BLIT_PROGRAM); C(BGIMAGE_PROGRAM); C(TINT_PROGRAM); + C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM); C(BLIT_PROGRAM); C(BGIMAGE_PROGRAM); C(TINT_PROGRAM); C(SEVEN_SEGMENT_PROGRAM); C(GLSL_VERSION); C(GL_VERSION); C(GL_VENDOR); diff --git a/kitty/utils.py b/kitty/utils.py index 260e32504..3713017ba 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -64,13 +64,14 @@ def platform_window_id(os_window_id: int) -> Optional[int]: return x11_window_id(os_window_id) -def load_shaders(name: str) -> Tuple[str, str]: +def load_shaders(name: str, vertex_name: str = '', fragment_name: str = '') -> Tuple[str, str]: from .fast_data_types import GLSL_VERSION - def load(which: str) -> str: - return read_kitty_resource(f'{name}_{which}.glsl').decode('utf-8').replace('GLSL_VERSION', str(GLSL_VERSION), 1) + def load(which: str, lname: str = '') -> str: + lname = lname or name + return read_kitty_resource(f'{lname}_{which}.glsl').decode('utf-8').replace('GLSL_VERSION', str(GLSL_VERSION), 1) - return load('vertex'), load('fragment') + return load('vertex', vertex_name), load('fragment', fragment_name) def safe_print(*a: Any, **k: Any) -> None: diff --git a/kitty/window.py b/kitty/window.py index ebba21c8c..75807953d 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -26,13 +26,13 @@ from .fast_data_types import ( CURSOR_UNDERLINE, DCS, DECORATION, DIM, GLFW_MOD_CONTROL, GRAPHICS_ALPHA_MASK_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, MARK, MARK_MASK, NO_CURSOR_SHAPE, OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, - SCROLL_PAGE, STRIKETHROUGH, TINT_PROGRAM, KeyEvent, Screen, add_timer, - add_window, cell_size_for_window, click_mouse_url, compile_program, - encode_key_for_tty, get_boss, get_clipboard_string, get_options, - init_cell_program, mouse_selection, move_cursor_to_mouse_if_in_prompt, - pt_to_px, set_clipboard_string, set_titlebar_color, set_window_padding, - set_window_render_data, update_window_title, update_window_visibility, - viewport_for_window + SCROLL_PAGE, SEVEN_SEGMENT_PROGRAM, STRIKETHROUGH, TINT_PROGRAM, KeyEvent, + Screen, add_timer, add_window, cell_size_for_window, click_mouse_url, + compile_program, encode_key_for_tty, get_boss, get_clipboard_string, + get_options, init_cell_program, mouse_selection, + move_cursor_to_mouse_if_in_prompt, pt_to_px, set_clipboard_string, + set_titlebar_color, set_window_padding, set_window_render_data, + update_window_title, update_window_visibility, viewport_for_window ) from .keys import keyboard_mode_name, mod_mask from .notify import NotificationCommand, handle_notification_cmd @@ -255,6 +255,8 @@ class LoadShaderPrograms: compile_program(BGIMAGE_PROGRAM, v, f) v, f = load_shaders('tint') compile_program(TINT_PROGRAM, v, f) + v, f = load_shaders('seven_segment', vertex_name='tint') + compile_program(SEVEN_SEGMENT_PROGRAM, v, f) init_cell_program()