mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-17 22:17:44 +02:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe92e29e89 | ||
|
|
c7c37deebb |
@@ -275,6 +275,7 @@ CELL_PROGRAM: int
|
|||||||
CELL_FG_PROGRAM: int
|
CELL_FG_PROGRAM: int
|
||||||
CELL_BG_PROGRAM: int
|
CELL_BG_PROGRAM: int
|
||||||
BLIT_PROGRAM: int
|
BLIT_PROGRAM: int
|
||||||
|
ROUNDED_RECT_PROGRAM: int
|
||||||
DECORATION: int
|
DECORATION: int
|
||||||
DIM: int
|
DIM: int
|
||||||
GRAPHICS_ALPHA_MASK_PROGRAM: int
|
GRAPHICS_ALPHA_MASK_PROGRAM: int
|
||||||
|
|||||||
@@ -151,6 +151,13 @@ static struct {
|
|||||||
void
|
void
|
||||||
set_gpu_viewport(unsigned w, unsigned h) { glViewport(0, 0, w, h); }
|
set_gpu_viewport(unsigned w, unsigned h) { glViewport(0, 0, w, h); }
|
||||||
|
|
||||||
|
Viewport
|
||||||
|
get_gpu_viewport(void) {
|
||||||
|
GLsizei v[4];
|
||||||
|
glGetIntegerv(GL_VIEWPORT, v);
|
||||||
|
return (Viewport){.left=v[0], .top=v[1], .width=v[2], .height=v[3]};
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
save_viewport_using_bottom_left_origin(GLsizei newx, GLsizei newy, GLsizei width, GLsizei height) {
|
save_viewport_using_bottom_left_origin(GLsizei newx, GLsizei newy, GLsizei width, GLsizei height) {
|
||||||
if (saved_viewports.used >= arraysz(saved_viewports.items)) fatal("Too many nested saved viewports");
|
if (saved_viewports.used >= arraysz(saved_viewports.items)) fatal("Too many nested saved viewports");
|
||||||
|
|||||||
@@ -29,10 +29,12 @@ typedef struct {
|
|||||||
GLint num_of_uniforms;
|
GLint num_of_uniforms;
|
||||||
} Program;
|
} Program;
|
||||||
|
|
||||||
|
typedef struct Viewport { unsigned left, top, width, height; } Viewport;
|
||||||
|
|
||||||
void gl_init(void);
|
void gl_init(void);
|
||||||
const char* gl_version_string(void);
|
const char* gl_version_string(void);
|
||||||
void set_gpu_viewport(unsigned w, unsigned h);
|
void set_gpu_viewport(unsigned w, unsigned h);
|
||||||
|
Viewport get_gpu_viewport(void);
|
||||||
void draw_quad(bool blend, unsigned instance_count);
|
void draw_quad(bool blend, unsigned instance_count);
|
||||||
void save_texture_as_png(uint32_t texture_id, const char *filename);
|
void save_texture_as_png(uint32_t texture_id, const char *filename);
|
||||||
void free_texture(GLuint *tex_id);
|
void free_texture(GLuint *tex_id);
|
||||||
|
|||||||
54
kitty/rounded_rect_fragment.glsl
Normal file
54
kitty/rounded_rect_fragment.glsl
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#pragma kitty_include_shader <alpha_blend.glsl>
|
||||||
|
#pragma kitty_include_shader <utils.glsl>
|
||||||
|
|
||||||
|
in vec2 dimensions;
|
||||||
|
out vec4 output_color;
|
||||||
|
|
||||||
|
uniform vec4 resolution_and_params;
|
||||||
|
uniform vec4 color;
|
||||||
|
uniform vec4 background_color;
|
||||||
|
uniform vec2 origin;
|
||||||
|
|
||||||
|
float rounded_rectangle_sdf(vec2 position, vec2 size, float radius) {
|
||||||
|
// signed distance field
|
||||||
|
size *= 0.5; // we work with a quadrant at a time
|
||||||
|
radius = min(radius, min(size.x, size.y)); // radius must be no larger than size
|
||||||
|
// Calculate distance vector from point to rectangle boundaries
|
||||||
|
vec2 q = abs(position) - (size - vec2(radius));
|
||||||
|
// Distance calculation
|
||||||
|
// 1. For points outside the rectangle (including corners): Euclidean distance to corner circle
|
||||||
|
// 2. For points along the edges: Perpendicular distance to the edge
|
||||||
|
// 3. For points inside: Negative distance to nearest edge
|
||||||
|
return length(max(q, 0.0)) + min(max(q.x, q.y), 0.0) - radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// Calculate normalized coordinates [-1, 1]
|
||||||
|
vec2 position = 2.0 * gl_FragCoord.xy / resolution_and_params.xy;
|
||||||
|
position = vec2(position.x - 1.0, 1.0 - position.y);
|
||||||
|
position -= origin; // shift origin
|
||||||
|
vec2 size = vec2(2, 2); // we are drawing in the full viewport
|
||||||
|
|
||||||
|
float thickness = resolution_and_params[2];
|
||||||
|
float corner_radius = resolution_and_params[3];
|
||||||
|
|
||||||
|
// Adjust co-ordinates to account for the aspect ratio of the screen
|
||||||
|
float aspect_ratio = resolution_and_params.x / resolution_and_params.y;
|
||||||
|
size.x *= aspect_ratio; position.x *= aspect_ratio;
|
||||||
|
|
||||||
|
// Calculate distance to rounded rectangle
|
||||||
|
float dist = rounded_rectangle_sdf(position, size, corner_radius);
|
||||||
|
|
||||||
|
// The border is outer - inner rects
|
||||||
|
float outer_edge = -dist;
|
||||||
|
float inner_edge = outer_edge - thickness;
|
||||||
|
|
||||||
|
// Smooth borders (anti-alias)
|
||||||
|
const float step_size = 0.005;
|
||||||
|
float alpha = smoothstep(-step_size, step_size, outer_edge) - smoothstep(-step_size, step_size, inner_edge);
|
||||||
|
vec4 ans = color;
|
||||||
|
ans.a *= alpha;
|
||||||
|
|
||||||
|
// pre-multiplied output
|
||||||
|
output_color = alpha_blend(ans, background_color);
|
||||||
|
}
|
||||||
17
kitty/rounded_rect_vertex.glsl
Normal file
17
kitty/rounded_rect_vertex.glsl
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#define left 0
|
||||||
|
#define top 1
|
||||||
|
#define right 2
|
||||||
|
#define bottom 3
|
||||||
|
|
||||||
|
const ivec2 vertex_pos_map[4] = ivec2[4](
|
||||||
|
ivec2(right, top),
|
||||||
|
ivec2(right, bottom),
|
||||||
|
ivec2(left, bottom),
|
||||||
|
ivec2(left, top)
|
||||||
|
);
|
||||||
|
const vec4 dest_rect = vec4(-1, 1, 1, -1);
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
ivec2 pos = vertex_pos_map[gl_VertexID];
|
||||||
|
gl_Position = vec4(dest_rect[pos.x], dest_rect[pos.y], 0, 1);
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ enum {
|
|||||||
TINT_PROGRAM,
|
TINT_PROGRAM,
|
||||||
TRAIL_PROGRAM,
|
TRAIL_PROGRAM,
|
||||||
BLIT_PROGRAM,
|
BLIT_PROGRAM,
|
||||||
|
ROUNDED_RECT_PROGRAM,
|
||||||
NUM_PROGRAMS
|
NUM_PROGRAMS
|
||||||
};
|
};
|
||||||
enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, SPRITE_DECORATIONS_MAP_UNIT };
|
enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, SPRITE_DECORATIONS_MAP_UNIT };
|
||||||
@@ -278,6 +279,41 @@ send_image_to_gpu(GLuint *tex_id, const void* data, GLsizei width, GLsizei heigh
|
|||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
|
// Rounded rect {{{
|
||||||
|
typedef struct {
|
||||||
|
Rounded_rectUniforms uniforms;
|
||||||
|
} RoundedRectProgramLayout;
|
||||||
|
static RoundedRectProgramLayout rounded_rect_program_layout;
|
||||||
|
|
||||||
|
static double
|
||||||
|
thickness_as_float(const OSWindow *os_window, unsigned level) {
|
||||||
|
level = MIN(level, arraysz(OPT(box_drawing_scale)));
|
||||||
|
double pts = OPT(box_drawing_scale)[level];
|
||||||
|
double dpi = (os_window->fonts_data->logical_dpi_x + os_window->fonts_data->logical_dpi_y) / 2.0;
|
||||||
|
return pts * dpi / 72.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
draw_rounded_rect(
|
||||||
|
const OSWindow *os_window, Viewport rect, unsigned framebuffer_width, unsigned framebuffer_height,
|
||||||
|
unsigned thickness_level, unsigned corner_radius_px,
|
||||||
|
color_type srgb_color, color_type srgb_background, float bg_alpha
|
||||||
|
) {
|
||||||
|
float thickness = (float)ceil(thickness_as_float(os_window, thickness_level));
|
||||||
|
thickness = (gl_size((unsigned)thickness, framebuffer_width) + gl_size((unsigned)thickness, framebuffer_height)) / 2.f;
|
||||||
|
float corner_radius = (2.f * corner_radius_px) / (rect.width + rect.height);
|
||||||
|
bind_program(ROUNDED_RECT_PROGRAM);
|
||||||
|
color_vec4(rounded_rect_program_layout.uniforms.color, srgb_color, 1.f);
|
||||||
|
color_vec4(rounded_rect_program_layout.uniforms.background_color, srgb_background, bg_alpha);
|
||||||
|
glUniform4f(rounded_rect_program_layout.uniforms.resolution_and_params, rect.width, rect.height, thickness, corner_radius);
|
||||||
|
glUniform2f(rounded_rect_program_layout.uniforms.origin, gl_size(rect.left, rect.width), -gl_size(rect.top, rect.height));
|
||||||
|
save_viewport_using_top_left_origin(rect.left, rect.top, rect.width, rect.height, framebuffer_height);
|
||||||
|
draw_quad(true, 0);
|
||||||
|
restore_viewport();
|
||||||
|
}
|
||||||
|
// }}}
|
||||||
|
|
||||||
// Cell {{{
|
// Cell {{{
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -339,6 +375,7 @@ init_cell_program(void) {
|
|||||||
get_uniform_locations_tint(TINT_PROGRAM, &tint_program_layout.uniforms);
|
get_uniform_locations_tint(TINT_PROGRAM, &tint_program_layout.uniforms);
|
||||||
get_uniform_locations_trail(TRAIL_PROGRAM, &trail_program_layout.uniforms);
|
get_uniform_locations_trail(TRAIL_PROGRAM, &trail_program_layout.uniforms);
|
||||||
get_uniform_locations_blit(BLIT_PROGRAM, &blit_program_layout.uniforms);
|
get_uniform_locations_blit(BLIT_PROGRAM, &blit_program_layout.uniforms);
|
||||||
|
get_uniform_locations_rounded_rect(ROUNDED_RECT_PROGRAM, &rounded_rect_program_layout.uniforms);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CELL_BUFFERS enum { cell_data_buffer, selection_buffer, uniform_buffer };
|
#define CELL_BUFFERS enum { cell_data_buffer, selection_buffer, uniform_buffer };
|
||||||
@@ -1199,6 +1236,8 @@ start_os_window_rendering(OSWindow *os_window) {
|
|||||||
static void
|
static void
|
||||||
stop_os_window_rendering(OSWindow *os_window, Tab *tab, Window *active_window) {
|
stop_os_window_rendering(OSWindow *os_window, Tab *tab, Window *active_window) {
|
||||||
if (OPT(cursor_trail) && tab->cursor_trail.needs_render) draw_cursor_trail(&tab->cursor_trail, active_window);
|
if (OPT(cursor_trail) && tab->cursor_trail.needs_render) draw_cursor_trail(&tab->cursor_trail, active_window);
|
||||||
|
draw_rounded_rect(os_window, (Viewport){.left=40, .top=40, .height=os_window->viewport_height - 80, .width=200},
|
||||||
|
os_window->viewport_width, os_window->viewport_height, 1, 30, 0xffffff, 0, 0);
|
||||||
if (os_window->needs_layers) {
|
if (os_window->needs_layers) {
|
||||||
set_framebuffer_to_use_for_output(0);
|
set_framebuffer_to_use_for_output(0);
|
||||||
bind_framebuffer_for_output(0);
|
bind_framebuffer_for_output(0);
|
||||||
@@ -1336,7 +1375,7 @@ init_shaders(PyObject *module) {
|
|||||||
#define C(x) if (PyModule_AddIntConstant(module, #x, x) != 0) { PyErr_NoMemory(); return false; }
|
#define C(x) if (PyModule_AddIntConstant(module, #x, x) != 0) { PyErr_NoMemory(); return false; }
|
||||||
C(CELL_PROGRAM); C(CELL_FG_PROGRAM); C(CELL_BG_PROGRAM); C(BORDERS_PROGRAM);
|
C(CELL_PROGRAM); C(CELL_FG_PROGRAM); C(CELL_BG_PROGRAM); C(BORDERS_PROGRAM);
|
||||||
C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM);
|
C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM);
|
||||||
C(BGIMAGE_PROGRAM); C(TINT_PROGRAM); C(TRAIL_PROGRAM); C(BLIT_PROGRAM);
|
C(BGIMAGE_PROGRAM); C(TINT_PROGRAM); C(TRAIL_PROGRAM); C(BLIT_PROGRAM); C(ROUNDED_RECT_PROGRAM);
|
||||||
C(GLSL_VERSION);
|
C(GLSL_VERSION);
|
||||||
C(GL_VERSION);
|
C(GL_VERSION);
|
||||||
C(GL_VENDOR);
|
C(GL_VENDOR);
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ from .fast_data_types import (
|
|||||||
MARK,
|
MARK,
|
||||||
MARK_MASK,
|
MARK_MASK,
|
||||||
REVERSE,
|
REVERSE,
|
||||||
|
ROUNDED_RECT_PROGRAM,
|
||||||
STRIKETHROUGH,
|
STRIKETHROUGH,
|
||||||
TINT_PROGRAM,
|
TINT_PROGRAM,
|
||||||
TRAIL_PROGRAM,
|
TRAIL_PROGRAM,
|
||||||
@@ -210,6 +211,7 @@ class LoadShaderPrograms:
|
|||||||
program_for('tint').compile(TINT_PROGRAM, allow_recompile)
|
program_for('tint').compile(TINT_PROGRAM, allow_recompile)
|
||||||
program_for('trail').compile(TRAIL_PROGRAM, allow_recompile)
|
program_for('trail').compile(TRAIL_PROGRAM, allow_recompile)
|
||||||
program_for('blit').compile(BLIT_PROGRAM, allow_recompile)
|
program_for('blit').compile(BLIT_PROGRAM, allow_recompile)
|
||||||
|
program_for('rounded_rect').compile(ROUNDED_RECT_PROGRAM, allow_recompile)
|
||||||
init_cell_program()
|
init_cell_program()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user