From 49be7799820579d007ae4415101bdb2ee36f8fbb Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Nov 2017 22:38:30 +0530 Subject: [PATCH] Port drawing of borders --- kitty/borders.py | 7 ++---- kitty/child-monitor.c | 7 ++++-- kitty/shaders.c | 57 +++++++++++++++---------------------------- kitty/state.c | 19 +++++++++++++++ kitty/state.h | 15 +++++++++++- 5 files changed, 60 insertions(+), 45 deletions(-) diff --git a/kitty/borders.py b/kitty/borders.py index 4a226179c..50b75d688 100644 --- a/kitty/borders.py +++ b/kitty/borders.py @@ -5,12 +5,10 @@ from functools import partial from itertools import chain -from .constants import viewport_size from .fast_data_types import ( - BORDERS_PROGRAM, add_borders_rect, compile_program, init_borders_program, - send_borders_rects + BORDERS_PROGRAM, add_borders_rect, compile_program, init_borders_program ) -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): @@ -74,4 +72,3 @@ class Borders: color, pw, g.left - pw, g.top - pw, g.right + pw, g.bottom + pw ) - send_borders_rects(viewport_size.width, viewport_size.height) diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index 273f22aa6..0bcf6ca43 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -558,11 +558,14 @@ render(double now) { unsigned int active_window_id = 0; 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); - if (window_rendered || tab_bar_changed || active_window_id != w->last_active_window_id) { - draw_borders(); + Tab *active_tab = w->tabs + w->active_tab; + 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); 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; + br->is_dirty = false; } } last_render_at = now; diff --git a/kitty/shaders.c b/kitty/shaders.c index e590ff9ce..5c90396f6 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -406,16 +406,11 @@ draw_cursor(CursorRenderInfo *cursor, bool is_focused) { // Borders {{{ enum BorderUniforms { BORDER_viewport, NUM_BORDER_UNIFORMS }; 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 init_borders_program() { Program *p = programs + BORDERS_PROGRAM; int left = NUM_BORDER_UNIFORMS; - border_vertex_array = create_vao(); 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 SET_LOC(viewport); @@ -423,47 +418,39 @@ init_borders_program() { } if (left) { fatal("Left over uniforms in borders program"); return; } #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); - 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); + + return vao_idx; } 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 (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_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); unbind_vertex_array(); 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 {{{ @@ -525,8 +512,6 @@ TWO_INT(unmap_vao_buffer) NO_ARG(init_cursor_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_INT(create_cell_vao) @@ -551,8 +536,6 @@ static PyMethodDef module_methods[] = { MW(unbind_program, METH_NOARGS), MW(init_cursor_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(create_cell_vao, METH_NOARGS), MW(create_graphics_vao, METH_NOARGS), diff --git a/kitty/state.c b/kitty/state.c index 4d0778a8e..ab07c0bc0 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -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); 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].border_rects.vao_idx = create_border_vao(); os_window->num_tabs++; 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 destroy_tab(Tab *tab) { 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 @@ -191,6 +194,19 @@ swap_windows(id_type os_window_id, id_type tab_id, unsigned int a, unsigned int 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 {{{ #define PYWRAP0(name) static PyObject* py##name(PyObject UNUSED *self) #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 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 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 color_as_int(PyObject *color) { @@ -369,6 +386,7 @@ KI(set_active_tab) KKI(set_active_window) KII(swap_tabs) KKII(swap_windows) +KK5I(add_borders_rect) #define M(name, arg_type) {#name, (PyCFunction)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(swap_tabs, METH_VARARGS), MW(swap_windows, METH_VARARGS), + MW(add_borders_rect, METH_VARARGS), MW(set_tab_bar_render_data, METH_VARARGS), MW(set_window_render_data, METH_VARARGS), MW(update_window_visibility, METH_VARARGS), diff --git a/kitty/state.h b/kitty/state.h index 9c021e3dd..dbefe69d7 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -56,10 +56,22 @@ typedef struct { double last_drag_scroll_at; } 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 { id_type id; unsigned int active_window, num_windows, capacity; Window *windows; + BorderRects border_rects; } Tab; #define MAX_KEY_COUNT 512 @@ -130,7 +142,8 @@ OSWindow* os_window_for_kitty_window(id_type); OSWindow* add_os_window(); OSWindow* current_os_window(); 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 *); void draw_cursor(CursorRenderInfo *, bool); void update_viewport_size(int, int);