mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-25 17:52:02 +02:00
Port drawing of borders
This commit is contained in:
@@ -5,12 +5,10 @@
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
from .constants import viewport_size
|
|
||||||
from .fast_data_types import (
|
from .fast_data_types import (
|
||||||
BORDERS_PROGRAM, add_borders_rect, compile_program, init_borders_program,
|
BORDERS_PROGRAM, add_borders_rect, compile_program, init_borders_program
|
||||||
send_borders_rects
|
|
||||||
)
|
)
|
||||||
from .utils import color_as_int, pt_to_px, load_shaders
|
from .utils import color_as_int, load_shaders, pt_to_px
|
||||||
|
|
||||||
|
|
||||||
def vertical_edge(color, width, top, bottom, left):
|
def vertical_edge(color, width, top, bottom, left):
|
||||||
@@ -74,4 +72,3 @@ class Borders:
|
|||||||
color, pw, g.left - pw, g.top - pw, g.right + pw,
|
color, pw, g.left - pw, g.top - pw, g.right + pw,
|
||||||
g.bottom + pw
|
g.bottom + pw
|
||||||
)
|
)
|
||||||
send_borders_rects(viewport_size.width, viewport_size.height)
|
|
||||||
|
|||||||
@@ -558,11 +558,14 @@ render(double now) {
|
|||||||
unsigned int active_window_id = 0;
|
unsigned int active_window_id = 0;
|
||||||
bool window_rendered = render_os_window(w, now, &active_window_id);
|
bool window_rendered = render_os_window(w, now, &active_window_id);
|
||||||
bool tab_bar_changed = w->num_tabs > 1 && (w->last_active_tab != w->active_tab || w->last_num_tabs != w->num_tabs);
|
bool tab_bar_changed = w->num_tabs > 1 && (w->last_active_tab != w->active_tab || w->last_num_tabs != w->num_tabs);
|
||||||
if (window_rendered || tab_bar_changed || active_window_id != w->last_active_window_id) {
|
Tab *active_tab = w->tabs + w->active_tab;
|
||||||
draw_borders();
|
BorderRects *br = &active_tab->border_rects;
|
||||||
|
if (window_rendered || tab_bar_changed || br->is_dirty || active_window_id != w->last_active_window_id) {
|
||||||
|
draw_borders(br->vao_idx, br->num_border_rects, br->rect_buf, br->is_dirty, w->viewport_width, w->viewport_height);
|
||||||
if (TD.screen && w->num_tabs > 1) draw_cells(TD.vao_idx, 0, TD.xstart, TD.ystart, TD.dx, TD.dy, TD.screen, w);
|
if (TD.screen && w->num_tabs > 1) draw_cells(TD.vao_idx, 0, TD.xstart, TD.ystart, TD.dx, TD.dy, TD.screen, w);
|
||||||
swap_window_buffers(w);
|
swap_window_buffers(w);
|
||||||
w->last_active_tab = w->active_tab; w->last_num_tabs = w->num_tabs; w->last_active_window_id = active_window_id;
|
w->last_active_tab = w->active_tab; w->last_num_tabs = w->num_tabs; w->last_active_window_id = active_window_id;
|
||||||
|
br->is_dirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
last_render_at = now;
|
last_render_at = now;
|
||||||
|
|||||||
@@ -406,16 +406,11 @@ draw_cursor(CursorRenderInfo *cursor, bool is_focused) {
|
|||||||
// Borders {{{
|
// Borders {{{
|
||||||
enum BorderUniforms { BORDER_viewport, NUM_BORDER_UNIFORMS };
|
enum BorderUniforms { BORDER_viewport, NUM_BORDER_UNIFORMS };
|
||||||
static GLint border_uniform_locations[NUM_BORDER_UNIFORMS] = {0};
|
static GLint border_uniform_locations[NUM_BORDER_UNIFORMS] = {0};
|
||||||
static ssize_t border_vertex_array;
|
|
||||||
static GLsizei num_border_rects = 0;
|
|
||||||
static GLuint rect_buf[5 * 1024];
|
|
||||||
static GLuint *rect_pos = NULL;
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_borders_program() {
|
init_borders_program() {
|
||||||
Program *p = programs + BORDERS_PROGRAM;
|
Program *p = programs + BORDERS_PROGRAM;
|
||||||
int left = NUM_BORDER_UNIFORMS;
|
int left = NUM_BORDER_UNIFORMS;
|
||||||
border_vertex_array = create_vao();
|
|
||||||
for (int i = 0; i < p->num_of_uniforms; i++, left--) {
|
for (int i = 0; i < p->num_of_uniforms; i++, left--) {
|
||||||
#define SET_LOC(which) if (strcmp(p->uniforms[i].name, #which) == 0) border_uniform_locations[BORDER_##which] = p->uniforms[i].location
|
#define SET_LOC(which) if (strcmp(p->uniforms[i].name, #which) == 0) border_uniform_locations[BORDER_##which] = p->uniforms[i].location
|
||||||
SET_LOC(viewport);
|
SET_LOC(viewport);
|
||||||
@@ -423,47 +418,39 @@ init_borders_program() {
|
|||||||
}
|
}
|
||||||
if (left) { fatal("Left over uniforms in borders program"); return; }
|
if (left) { fatal("Left over uniforms in borders program"); return; }
|
||||||
#undef SET_LOC
|
#undef SET_LOC
|
||||||
add_buffer_to_vao(border_vertex_array, GL_ARRAY_BUFFER);
|
}
|
||||||
add_attribute_to_vao(BORDERS_PROGRAM, border_vertex_array, "rect",
|
|
||||||
|
ssize_t
|
||||||
|
create_border_vao() {
|
||||||
|
ssize_t vao_idx = create_vao();
|
||||||
|
|
||||||
|
add_buffer_to_vao(vao_idx, GL_ARRAY_BUFFER);
|
||||||
|
add_attribute_to_vao(BORDERS_PROGRAM, vao_idx, "rect",
|
||||||
/*size=*/4, /*dtype=*/GL_UNSIGNED_INT, /*stride=*/sizeof(GLuint)*5, /*offset=*/0, /*divisor=*/1);
|
/*size=*/4, /*dtype=*/GL_UNSIGNED_INT, /*stride=*/sizeof(GLuint)*5, /*offset=*/0, /*divisor=*/1);
|
||||||
add_attribute_to_vao(BORDERS_PROGRAM, border_vertex_array, "rect_color",
|
add_attribute_to_vao(BORDERS_PROGRAM, vao_idx, "rect_color",
|
||||||
/*size=*/1, /*dtype=*/GL_UNSIGNED_INT, /*stride=*/sizeof(GLuint)*5, /*offset=*/(void*)(sizeof(GLuint)*4), /*divisor=*/1);
|
/*size=*/1, /*dtype=*/GL_UNSIGNED_INT, /*stride=*/sizeof(GLuint)*5, /*offset=*/(void*)(sizeof(GLuint)*4), /*divisor=*/1);
|
||||||
|
|
||||||
|
return vao_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
draw_borders() {
|
draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_buf, bool rect_data_is_dirty, uint32_t viewport_width, uint32_t viewport_height) {
|
||||||
if (num_border_rects) {
|
if (num_border_rects) {
|
||||||
|
if (rect_data_is_dirty) {
|
||||||
|
size_t sz = sizeof(GLuint) * 5 * num_border_rects;
|
||||||
|
void *borders_buf_address = alloc_and_map_vao_buffer(vao_idx, sz, 0, GL_STATIC_DRAW, GL_WRITE_ONLY);
|
||||||
|
if (borders_buf_address) memcpy(borders_buf_address, rect_buf, sz);
|
||||||
|
unmap_vao_buffer(vao_idx, 0);
|
||||||
|
}
|
||||||
bind_program(BORDERS_PROGRAM);
|
bind_program(BORDERS_PROGRAM);
|
||||||
bind_vertex_array(border_vertex_array);
|
glUniform2ui(border_uniform_locations[BORDER_viewport], viewport_width, viewport_height);
|
||||||
|
bind_vertex_array(vao_idx);
|
||||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, num_border_rects);
|
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, num_border_rects);
|
||||||
unbind_vertex_array();
|
unbind_vertex_array();
|
||||||
unbind_program();
|
unbind_program();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
add_borders_rect(GLuint left, GLuint top, GLuint right, GLuint bottom, GLuint color) {
|
|
||||||
if (!left && !top && !right && !bottom) { num_border_rects = 0; rect_pos = rect_buf; return; }
|
|
||||||
num_border_rects++;
|
|
||||||
*(rect_pos++) = left;
|
|
||||||
*(rect_pos++) = top;
|
|
||||||
*(rect_pos++) = right;
|
|
||||||
*(rect_pos++) = bottom;
|
|
||||||
*(rect_pos++) = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
send_borders_rects(GLuint vw, GLuint vh) {
|
|
||||||
if (num_border_rects) {
|
|
||||||
size_t sz = sizeof(GLuint) * 5 * num_border_rects;
|
|
||||||
void *borders_buf_address = alloc_and_map_vao_buffer(border_vertex_array, sz, 0, GL_STATIC_DRAW, GL_WRITE_ONLY);
|
|
||||||
if (borders_buf_address) memcpy(borders_buf_address, rect_buf, sz);
|
|
||||||
unmap_vao_buffer(border_vertex_array, 0);
|
|
||||||
}
|
|
||||||
bind_program(BORDERS_PROGRAM);
|
|
||||||
glUniform2ui(border_uniform_locations[BORDER_viewport], vw, vh);
|
|
||||||
unbind_program();
|
|
||||||
}
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
// Python API {{{
|
// Python API {{{
|
||||||
@@ -525,8 +512,6 @@ TWO_INT(unmap_vao_buffer)
|
|||||||
NO_ARG(init_cursor_program)
|
NO_ARG(init_cursor_program)
|
||||||
|
|
||||||
NO_ARG(init_borders_program)
|
NO_ARG(init_borders_program)
|
||||||
PYWRAP1(add_borders_rect) { unsigned int a, b, c, d, e; PA("IIIII", &a, &b, &c, &d, &e); add_borders_rect(a, b, c, d, e); Py_RETURN_NONE; }
|
|
||||||
TWO_INT(send_borders_rects)
|
|
||||||
|
|
||||||
NO_ARG(init_cell_program)
|
NO_ARG(init_cell_program)
|
||||||
NO_ARG_INT(create_cell_vao)
|
NO_ARG_INT(create_cell_vao)
|
||||||
@@ -551,8 +536,6 @@ static PyMethodDef module_methods[] = {
|
|||||||
MW(unbind_program, METH_NOARGS),
|
MW(unbind_program, METH_NOARGS),
|
||||||
MW(init_cursor_program, METH_NOARGS),
|
MW(init_cursor_program, METH_NOARGS),
|
||||||
MW(init_borders_program, METH_NOARGS),
|
MW(init_borders_program, METH_NOARGS),
|
||||||
MW(add_borders_rect, METH_VARARGS),
|
|
||||||
MW(send_borders_rects, METH_VARARGS),
|
|
||||||
MW(init_cell_program, METH_NOARGS),
|
MW(init_cell_program, METH_NOARGS),
|
||||||
MW(create_cell_vao, METH_NOARGS),
|
MW(create_cell_vao, METH_NOARGS),
|
||||||
MW(create_graphics_vao, METH_NOARGS),
|
MW(create_graphics_vao, METH_NOARGS),
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ add_tab(id_type os_window_id, id_type id) {
|
|||||||
ensure_space_for(os_window, tabs, Tab, os_window->num_tabs + 1, capacity, 1, true);
|
ensure_space_for(os_window, tabs, Tab, os_window->num_tabs + 1, capacity, 1, true);
|
||||||
memset(os_window->tabs + os_window->num_tabs, 0, sizeof(Tab));
|
memset(os_window->tabs + os_window->num_tabs, 0, sizeof(Tab));
|
||||||
os_window->tabs[os_window->num_tabs].id = id;
|
os_window->tabs[os_window->num_tabs].id = id;
|
||||||
|
os_window->tabs[os_window->num_tabs].border_rects.vao_idx = create_border_vao();
|
||||||
os_window->num_tabs++;
|
os_window->num_tabs++;
|
||||||
END_WITH_OS_WINDOW
|
END_WITH_OS_WINDOW
|
||||||
}
|
}
|
||||||
@@ -121,6 +122,8 @@ remove_window(id_type os_window_id, id_type tab_id, id_type id) {
|
|||||||
static inline void
|
static inline void
|
||||||
destroy_tab(Tab *tab) {
|
destroy_tab(Tab *tab) {
|
||||||
for (size_t i = tab->num_windows; i > 0; i--) remove_window_inner(tab, tab->windows[ i - 1].id);
|
for (size_t i = tab->num_windows; i > 0; i--) remove_window_inner(tab, tab->windows[ i - 1].id);
|
||||||
|
remove_vao(tab->border_rects.vao_idx);
|
||||||
|
free(tab->border_rects.rect_buf); tab->border_rects.rect_buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@@ -191,6 +194,19 @@ swap_windows(id_type os_window_id, id_type tab_id, unsigned int a, unsigned int
|
|||||||
END_WITH_TAB;
|
END_WITH_TAB;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_borders_rect(id_type os_window_id, id_type tab_id, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom, uint32_t color) {
|
||||||
|
WITH_TAB(os_window_id, tab_id)
|
||||||
|
BorderRects *br = &tab->border_rects;
|
||||||
|
br->is_dirty = true;
|
||||||
|
if (!left && !top && !right && !bottom) { br->num_border_rects = 0; return; }
|
||||||
|
ensure_space_for(br, rect_buf, BorderRect, br->num_border_rects + 1, capacity, 32, false);
|
||||||
|
BorderRect *r = br->rect_buf + br->num_border_rects++;
|
||||||
|
r->left = left; r->right = right; r->top = top; r->bottom = bottom; r->color = color;
|
||||||
|
END_WITH_TAB
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Python API {{{
|
// Python API {{{
|
||||||
#define PYWRAP0(name) static PyObject* py##name(PyObject UNUSED *self)
|
#define PYWRAP0(name) static PyObject* py##name(PyObject UNUSED *self)
|
||||||
#define PYWRAP1(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args)
|
#define PYWRAP1(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args)
|
||||||
@@ -206,6 +222,7 @@ swap_windows(id_type os_window_id, id_type tab_id, unsigned int a, unsigned int
|
|||||||
#define KII(name) PYWRAP1(name) { id_type a; unsigned int b, c; PA("KII", &a, &b, &c); name(a, b, c); Py_RETURN_NONE; }
|
#define KII(name) PYWRAP1(name) { id_type a; unsigned int b, c; PA("KII", &a, &b, &c); name(a, b, c); Py_RETURN_NONE; }
|
||||||
#define KKI(name) PYWRAP1(name) { id_type a, b; unsigned int c; PA("KKI", &a, &b, &c); name(a, b, c); Py_RETURN_NONE; }
|
#define KKI(name) PYWRAP1(name) { id_type a, b; unsigned int c; PA("KKI", &a, &b, &c); name(a, b, c); Py_RETURN_NONE; }
|
||||||
#define KKII(name) PYWRAP1(name) { id_type a, b; unsigned int c, d; PA("KKII", &a, &b, &c, &d); name(a, b, c, d); Py_RETURN_NONE; }
|
#define KKII(name) PYWRAP1(name) { id_type a, b; unsigned int c, d; PA("KKII", &a, &b, &c, &d); name(a, b, c, d); Py_RETURN_NONE; }
|
||||||
|
#define KK5I(name) PYWRAP1(name) { id_type a, b; unsigned int c, d, e, f, g; PA("KKIIIII", &a, &b, &c, &d, &e, &f, &g); name(a, b, c, d, e, f, g); Py_RETURN_NONE; }
|
||||||
|
|
||||||
static inline color_type
|
static inline color_type
|
||||||
color_as_int(PyObject *color) {
|
color_as_int(PyObject *color) {
|
||||||
@@ -369,6 +386,7 @@ KI(set_active_tab)
|
|||||||
KKI(set_active_window)
|
KKI(set_active_window)
|
||||||
KII(swap_tabs)
|
KII(swap_tabs)
|
||||||
KKII(swap_windows)
|
KKII(swap_windows)
|
||||||
|
KK5I(add_borders_rect)
|
||||||
|
|
||||||
#define M(name, arg_type) {#name, (PyCFunction)name, arg_type, NULL}
|
#define M(name, arg_type) {#name, (PyCFunction)name, arg_type, NULL}
|
||||||
#define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
|
#define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
|
||||||
@@ -386,6 +404,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
MW(set_active_window, METH_VARARGS),
|
MW(set_active_window, METH_VARARGS),
|
||||||
MW(swap_tabs, METH_VARARGS),
|
MW(swap_tabs, METH_VARARGS),
|
||||||
MW(swap_windows, METH_VARARGS),
|
MW(swap_windows, METH_VARARGS),
|
||||||
|
MW(add_borders_rect, METH_VARARGS),
|
||||||
MW(set_tab_bar_render_data, METH_VARARGS),
|
MW(set_tab_bar_render_data, METH_VARARGS),
|
||||||
MW(set_window_render_data, METH_VARARGS),
|
MW(set_window_render_data, METH_VARARGS),
|
||||||
MW(update_window_visibility, METH_VARARGS),
|
MW(update_window_visibility, METH_VARARGS),
|
||||||
|
|||||||
@@ -56,10 +56,22 @@ typedef struct {
|
|||||||
double last_drag_scroll_at;
|
double last_drag_scroll_at;
|
||||||
} Window;
|
} Window;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t left, top, right, bottom, color;
|
||||||
|
} BorderRect;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BorderRect *rect_buf;
|
||||||
|
unsigned int num_border_rects, capacity;
|
||||||
|
bool is_dirty;
|
||||||
|
ssize_t vao_idx;
|
||||||
|
} BorderRects;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
id_type id;
|
id_type id;
|
||||||
unsigned int active_window, num_windows, capacity;
|
unsigned int active_window, num_windows, capacity;
|
||||||
Window *windows;
|
Window *windows;
|
||||||
|
BorderRects border_rects;
|
||||||
} Tab;
|
} Tab;
|
||||||
|
|
||||||
#define MAX_KEY_COUNT 512
|
#define MAX_KEY_COUNT 512
|
||||||
@@ -130,7 +142,8 @@ OSWindow* os_window_for_kitty_window(id_type);
|
|||||||
OSWindow* add_os_window();
|
OSWindow* add_os_window();
|
||||||
OSWindow* current_os_window();
|
OSWindow* current_os_window();
|
||||||
bool drag_scroll(Window *, OSWindow*);
|
bool drag_scroll(Window *, OSWindow*);
|
||||||
void draw_borders();
|
void draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_buf, bool rect_data_is_dirty, uint32_t viewport_width, uint32_t viewport_height);
|
||||||
|
ssize_t create_border_vao();
|
||||||
bool draw_cells(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *);
|
bool draw_cells(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *);
|
||||||
void draw_cursor(CursorRenderInfo *, bool);
|
void draw_cursor(CursorRenderInfo *, bool);
|
||||||
void update_viewport_size(int, int);
|
void update_viewport_size(int, int);
|
||||||
|
|||||||
Reference in New Issue
Block a user