From 642738454c13c93ad690a411a0a99a435ddf0995 Mon Sep 17 00:00:00 2001 From: Luflosi Date: Sun, 10 Mar 2019 19:18:42 +0100 Subject: [PATCH] WIP --- kitty/child-monitor.c | 28 ++++++++++----- kitty/fonts.c | 2 +- kitty/gl.c | 6 +++- kitty/gl.h | 2 +- kitty/glfw.c | 2 +- kitty/keys.c | 1 + kitty/mouse.c | 23 ++++++------ kitty/screen.c | 11 ++++++ kitty/screen.h | 4 ++- kitty/scroll_fragment.glsl | 11 ++++++ kitty/scroll_vertex.glsl | 13 +++++++ kitty/shaders.c | 72 ++++++++++++++++++++++++++++++++++++-- kitty/state.c | 1 + kitty/state.h | 7 ++-- kitty/window.py | 10 +++++- 15 files changed, 163 insertions(+), 30 deletions(-) create mode 100644 kitty/scroll_fragment.glsl create mode 100644 kitty/scroll_vertex.glsl diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index f4a5320eb3e..69d53bdce8e 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -246,7 +246,7 @@ schedule_write_to_child(unsigned long id, unsigned int num, ...) { } screen->write_buf_sz = screen->write_buf_used + sz; screen->write_buf = PyMem_RawRealloc(screen->write_buf, screen->write_buf_sz); - if (screen->write_buf == NULL) { fatal("Out of memory."); } + if (screen->write_buf == NULL) fatal("Out of memory."); } va_start(ap, num); for (unsigned int i = 0; i < num; i++) { @@ -259,7 +259,7 @@ schedule_write_to_child(unsigned long id, unsigned int num, ...) { if (screen->write_buf_sz > BUFSIZ && screen->write_buf_used < BUFSIZ) { screen->write_buf_sz = BUFSIZ; screen->write_buf = PyMem_RawRealloc(screen->write_buf, screen->write_buf_sz); - if (screen->write_buf == NULL) { fatal("Out of memory."); } + if (screen->write_buf == NULL) fatal("Out of memory."); } if (screen->write_buf_used) wakeup_io_loop(self, false); screen_mutex(unlock, write); @@ -589,8 +589,13 @@ prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int * static inline void render_os_window(OSWindow *os_window, monotonic_t now, unsigned int active_window_id, color_type active_window_bg, unsigned int num_visible_windows, bool all_windows_have_same_bg) { + static bool first_time = true; + if (first_time) { + setup_scroll(os_window); + first_time = false; + } // ensure all pixels are cleared to background color at least once in every buffer - if (os_window->clear_count++ < 3) blank_os_window(os_window); + if (os_window->clear_count++ < 2) blank_os_window(os_window); Tab *tab = os_window->tabs + os_window->active_tab; BorderRects *br = &tab->border_rects; bool static_live_resize_in_progress = os_window->live_resize.in_progress && OPT(resize_draw_strategy) == RESIZE_DRAW_STATIC; @@ -603,19 +608,24 @@ render_os_window(OSWindow *os_window, monotonic_t now, unsigned int active_windo draw_borders(br->vao_idx, br->num_border_rects, br->rect_buf, br->is_dirty, os_window->viewport_width, os_window->viewport_height, active_window_bg, num_visible_windows, all_windows_have_same_bg, os_window); br->is_dirty = false; } - if (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) draw_cells(TD.vao_idx, 0, TD.xstart, TD.ystart, TD.dx * x_ratio, TD.dy * y_ratio, TD.screen, os_window, true, false); for (unsigned int i = 0; i < tab->num_windows; i++) { Window *w = tab->windows + i; if (w->visible && WD.screen) { + before_render(); bool is_active_window = i == tab->active_window; - draw_cells(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx * x_ratio, WD.dy * y_ratio, WD.screen, os_window, is_active_window, true); - if (WD.screen->start_visual_bell_at != 0) { - monotonic_t bell_left = OPT(visual_bell_duration) - (now - WD.screen->start_visual_bell_at); - set_maximum_wait(bell_left); + if (WD.screen->render_not_only_pixel_scroll) { + WD.screen->render_not_only_pixel_scroll = false; + draw_cells(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx * x_ratio, WD.dy * y_ratio, WD.screen, os_window, is_active_window, true); + if (WD.screen->start_visual_bell_at != 0) { + monotonic_t bell_left = OPT(visual_bell_duration) - (now - WD.screen->start_visual_bell_at); + set_maximum_wait(bell_left); + } } + after_render(os_window, (WD.screen->scrolled_by_pixels * 2.0) / os_window->viewport_height); w->cursor_visible_at_last_render = WD.screen->cursor_render_info.is_visible; w->last_cursor_x = WD.screen->cursor_render_info.x; w->last_cursor_y = WD.screen->cursor_render_info.y; w->last_cursor_shape = WD.screen->cursor_render_info.shape; } } + if (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) draw_cells(TD.vao_idx, 0, TD.xstart, TD.ystart, TD.dx, TD.dy, TD.screen, os_window, true, false); swap_window_buffers(os_window); os_window->last_active_tab = os_window->active_tab; os_window->last_num_tabs = os_window->num_tabs; os_window->last_active_window_id = active_window_id; os_window->focused_at_last_render = os_window->is_focused; @@ -688,7 +698,7 @@ render(monotonic_t now, bool input_read) { bool needs_render = w->is_damaged || w->live_resize.in_progress; if (w->viewport_size_dirty) { w->clear_count = 0; - update_surface_size(w->viewport_width, w->viewport_height, w->offscreen_texture_id); + update_surface_size(w->viewport_width, w->viewport_height, w->offscreen_texture_id, w->scroll_texture_id); w->viewport_size_dirty = false; needs_render = true; } diff --git a/kitty/fonts.c b/kitty/fonts.c index d35dc902a29..747fe64d987 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -720,7 +720,7 @@ extract_cell_from_canvas(FontGroup *fg, unsigned int i, unsigned int num_cells) static inline void render_group(FontGroup *fg, unsigned int num_cells, unsigned int num_glyphs, CPUCell *cpu_cells, GPUCell *gpu_cells, hb_glyph_info_t *info, hb_glyph_position_t *positions, Font *font, glyph_index glyph, ExtraGlyphs *extra_glyphs, bool center_glyph) { - static SpritePosition* sprite_position[16]; + static SpritePosition* sprite_position[16]; // TODO: Remove magic number int error = 0; num_cells = MIN(arraysz(sprite_position), num_cells); for (unsigned int i = 0; i < num_cells; i++) { diff --git a/kitty/gl.c b/kitty/gl.c index cab14738a3f..de9322c9e4d 100644 --- a/kitty/gl.c +++ b/kitty/gl.c @@ -67,8 +67,12 @@ gl_init() { } void -update_surface_size(int w, int h, GLuint offscreen_texture_id) { +update_surface_size(int w, int h, GLuint offscreen_texture_id, GLuint scroll_texture_id) { glViewport(0, 0, w, h); + if (scroll_texture_id) { + glBindTexture(GL_TEXTURE_2D, scroll_texture_id); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + } if (offscreen_texture_id) { glBindTexture(GL_TEXTURE_2D, offscreen_texture_id); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); diff --git a/kitty/gl.h b/kitty/gl.h index 520a5ae253e..41db56d520e 100644 --- a/kitty/gl.h +++ b/kitty/gl.h @@ -33,7 +33,7 @@ typedef struct { void gl_init(void); -void update_surface_size(int w, int h, GLuint offscreen_texture_id); +void update_surface_size(int w, int h, GLuint offscreen_texture_id, GLuint scroll_texture_id); void free_texture(GLuint *tex_id); void free_framebuffer(GLuint *fb_id); void remove_vao(ssize_t vao_idx); diff --git a/kitty/glfw.c b/kitty/glfw.c index 6212af8c722..56949624f56 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -203,7 +203,7 @@ framebuffer_size_callback(GLFWwindow *w, int width, int height) { window->live_resize.width = MAX(0, width); window->live_resize.height = MAX(0, height); window->live_resize.num_of_resize_events++; make_os_window_context_current(window); - update_surface_size(width, height, window->offscreen_texture_id); + update_surface_size(width, height, window->offscreen_texture_id, window->scroll_texture_id); request_tick_callback(); } else log_error("Ignoring resize request for tiny size: %dx%d", width, height); global_state.callback_os_window = NULL; diff --git a/kitty/keys.c b/kitty/keys.c index a4a495c4398..4560969c4fd 100644 --- a/kitty/keys.c +++ b/kitty/keys.c @@ -187,6 +187,7 @@ on_key_input(GLFWkeyevent *ev) { } if (screen->scrolled_by && action == GLFW_PRESS && !is_modifier_key(key)) { screen_history_scroll(screen, SCROLL_FULL, false); // scroll back to bottom + pixel_scroll(screen, 0); } bool ok_to_send = action == GLFW_PRESS || action == GLFW_REPEAT || screen->modes.mEXTENDED_KEYBOARD; if (ok_to_send) { diff --git a/kitty/mouse.c b/kitty/mouse.c index 403eb0ba659..8a103143600 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -192,6 +192,7 @@ do_drag_scroll(Window *w, bool upwards) { Screen *screen = w->render_data.screen; if (screen->linebuf == screen->main_linebuf) { screen_history_scroll(screen, SCROLL_LINE, upwards); + pixel_scroll(screen, 0); update_drag(false, w, false, 0); if (mouse_cursor_shape != ARROW) { mouse_cursor_shape = ARROW; @@ -651,18 +652,12 @@ scroll_event(double UNUSED xoffset, double yoffset, int flags) { int s; bool is_high_resolution = flags & 1; + double pixels = screen->pending_scroll_pixels; if (is_high_resolution) { yoffset *= OPT(touch_scroll_multiplier); - if (yoffset * screen->pending_scroll_pixels < 0) { - screen->pending_scroll_pixels = 0; // change of direction - } - double pixels = screen->pending_scroll_pixels + yoffset; - if (fabs(pixels) < global_state.callback_os_window->fonts_data->cell_height) { - screen->pending_scroll_pixels = pixels; - return; - } + pixels += yoffset; s = (int)round(pixels) / (int)global_state.callback_os_window->fonts_data->cell_height; - screen->pending_scroll_pixels = pixels - s * (int) global_state.callback_os_window->fonts_data->cell_height; + pixels = pixels - s * (int) global_state.callback_os_window->fonts_data->cell_height; } else { if (screen->linebuf == screen->main_linebuf || !screen->modes.mouse_tracking_mode) { // Only use wheel_scroll_multiplier if we are scrolling kitty scrollback or in mouse @@ -677,13 +672,18 @@ scroll_event(double UNUSED xoffset, double yoffset, int flags) { // apparently on cocoa some mice generate really small yoffset values // when scrolling slowly https://github.com/kovidgoyal/kitty/issues/1238 if (s == 0 && yoffset != 0) s = yoffset > 0 ? 1 : -1; - screen->pending_scroll_pixels = 0; } - if (s == 0) return; bool upwards = s > 0; + //printf("asdf %f\n", pixels); if (screen->linebuf == screen->main_linebuf) { screen_history_scroll(screen, abs(s), upwards); + if (screen->scrolled_by == 0 && pixels < 0) pixels = 0; + if (screen->scrolled_by == screen->historybuf->count && pixels > 0) pixels = 0; + screen->pending_scroll_pixels = pixels; + pixel_scroll(screen, (int)pixels); } else { + pixels = 0.0; + pixel_scroll(screen, (int)pixels); if (screen->modes.mouse_tracking_mode) { int sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : GLFW_MOUSE_BUTTON_5, PRESS, 0); if (sz > 0) { @@ -696,6 +696,7 @@ scroll_event(double UNUSED xoffset, double yoffset, int flags) { fake_scroll(abs(s), upwards); } } + screen->pending_scroll_pixels = pixels; } static PyObject* diff --git a/kitty/screen.c b/kitty/screen.c index cc61969651d..f0eb78b9f27 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -97,6 +97,8 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { self->modes = empty_modes; self->is_dirty = true; self->scroll_changed = false; + self->pixel_scroll_changed = false; + self->render_not_only_pixel_scroll = false; self->margin_top = 0; self->margin_bottom = self->lines - 1; self->history_line_added_count = 0; RESET_CHARSETS; @@ -657,6 +659,7 @@ screen_toggle_screen_buffer(Screen *self) { self->grman = self->main_grman; } screen_history_scroll(self, SCROLL_FULL, false); + pixel_scroll(self, 0); self->is_dirty = true; self->selection = EMPTY_SELECTION; } @@ -1199,6 +1202,7 @@ screen_erase_in_display(Screen *self, unsigned int how, bool private) { self->scrolled_by = 0; self->scroll_changed = true; } + pixel_scroll(self, 0); } } @@ -2205,6 +2209,12 @@ screen_selection_range_for_word(Screen *self, const index_type x, const index_ty #undef is_ok } +void pixel_scroll(Screen *self, int amt) { + //printf("pixel_scroll(%d)\n", amt); + self->scrolled_by_pixels = amt; + self->pixel_scroll_changed = true; +} + bool screen_history_scroll(Screen *self, int amt, bool upwards) { switch(amt) { @@ -2239,6 +2249,7 @@ static PyObject* scroll(Screen *self, PyObject *args) { int amt, upwards; if (!PyArg_ParseTuple(args, "ip", &amt, &upwards)) return NULL; + pixel_scroll(self, 0); if (screen_history_scroll(self, amt, upwards)) { Py_RETURN_TRUE; } Py_RETURN_FALSE; } diff --git a/kitty/screen.h b/kitty/screen.h index d337a5a5c14..9e19b8304a6 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -76,6 +76,7 @@ typedef struct { PyObject_HEAD unsigned int columns, lines, margin_top, margin_bottom, charset, scrolled_by; + int scrolled_by_pixels; double pending_scroll_pixels; CellPixelSize cell_size; OverlayLine overlay_line; @@ -87,7 +88,7 @@ typedef struct { IterationData selection, url; unsigned int cursor_x, cursor_y, scrolled_by; } last_rendered; - bool use_latin1, is_dirty, scroll_changed, reload_all_gpu_data; + bool use_latin1, is_dirty, scroll_changed, pixel_scroll_changed, reload_all_gpu_data, render_not_only_pixel_scroll; Cursor *cursor; SavepointBuffer main_savepoints, alt_savepoints; SavemodesBuffer modes_savepoints; @@ -197,6 +198,7 @@ bool screen_selection_range_for_line(Screen *self, index_type y, index_type *sta bool screen_selection_range_for_word(Screen *self, const index_type x, const index_type y, index_type *, index_type *, index_type *start, index_type *end, bool); void screen_start_selection(Screen *self, index_type x, index_type y, bool, bool, SelectionExtendMode); void screen_update_selection(Screen *self, index_type x, index_type y, bool in_left_half, bool ended, bool start_extended_selection); +void pixel_scroll(Screen *self, int amt); bool screen_history_scroll(Screen *self, int amt, bool upwards); Line* screen_visual_line(Screen *self, index_type y); unsigned long screen_current_char_width(Screen *self); diff --git a/kitty/scroll_fragment.glsl b/kitty/scroll_fragment.glsl new file mode 100644 index 00000000000..4d3ab781a62 --- /dev/null +++ b/kitty/scroll_fragment.glsl @@ -0,0 +1,11 @@ +#version GLSL_VERSION +out vec4 FragColor; + +in vec2 TexCoords; + +uniform sampler2D screenTexture; + +void main() +{ + FragColor = texture(screenTexture, TexCoords); +} diff --git a/kitty/scroll_vertex.glsl b/kitty/scroll_vertex.glsl new file mode 100644 index 00000000000..1a9387754e9 --- /dev/null +++ b/kitty/scroll_vertex.glsl @@ -0,0 +1,13 @@ +#version GLSL_VERSION +layout (location = 0) in vec2 aPos; +layout (location = 1) in vec2 aTexCoords; + +uniform float offset; + +out vec2 TexCoords; + +void main() +{ + gl_Position = vec4(aPos.x, aPos.y - offset, 0.0, 1.0); + TexCoords = aTexCoords; +} diff --git a/kitty/shaders.c b/kitty/shaders.c index 3543d5bb806..1a18c7c8716 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, SCROLL_PROGRAM, NUM_PROGRAMS }; enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT, BGIMAGE_UNIT }; // Sprites {{{ @@ -82,6 +82,7 @@ copy_image_sub_data(GLuint src_texture_id, GLuint dest_texture_id, unsigned int static void realloc_sprite_texture(FONTS_DATA_HANDLE fg) { + printf("realloc_sprite_texture\n"); GLuint tex; glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D_ARRAY, tex); @@ -121,6 +122,7 @@ ensure_sprite_map(FONTS_DATA_HANDLE fg) { void send_sprite_to_gpu(FONTS_DATA_HANDLE fg, unsigned int x, unsigned int y, unsigned int z, pixel *buf) { + printf("%d\t%d\t%d\n", x, y, z); SpriteMap *sprite_map = (SpriteMap*)fg->sprite_map; unsigned int xnum, ynum, znum; sprite_tracker_current_layout(fg, &xnum, &ynum, &znum); @@ -163,6 +165,8 @@ typedef struct { } CellProgramLayout; static CellProgramLayout cell_program_layouts[NUM_PROGRAMS]; +static GLuint scroll_framebuffer = 0; +static unsigned int quadVAO, quadVBO; static ssize_t blit_vertex_array; typedef struct { GLint image_location, tiled_location, sizes_location, opacity_location, premult_location; @@ -199,6 +203,62 @@ init_cell_program(void) { tint_program_layout.edges_location = get_uniform_location(TINT_PROGRAM, "edges"); } +void setup_scroll(OSWindow *os_window) { + glGenFramebuffers(1, &scroll_framebuffer); + glBindFramebuffer(GL_FRAMEBUFFER, scroll_framebuffer); + glGenTextures(1, &os_window->scroll_texture_id); + glBindTexture(GL_TEXTURE_2D, os_window->scroll_texture_id); + printf("%d %d\n", os_window->viewport_width, os_window->viewport_height); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, os_window->viewport_width, os_window->viewport_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 640, 400, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glBindTexture(GL_TEXTURE_2D, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, os_window->scroll_texture_id, 0); + + float quadVertices[] = { // vertex attributes for a quad that fills the entire screen in Normalized Device Coordinates. + // positions // texCoords + -1.0f, 1.0f, 0.0f, 1.0f, + -1.0f, -1.0f, 0.0f, 0.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + + -1.0f, 1.0f, 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, 0.0f, + 1.0f, 1.0f, 1.0f, 1.0f + }; + + glGenVertexArrays(1, &quadVAO); + glGenBuffers(1, &quadVBO); + glBindVertexArray(quadVAO); + glBindBuffer(GL_ARRAY_BUFFER, quadVBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices, GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float))); +} + +void before_render() { + // first pass + glBindFramebuffer(GL_FRAMEBUFFER, scroll_framebuffer); + //glClearColor(0.1f, 0.1f, 0.1f, 1.0f); + //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // we're not using the stencil buffer now +} + +void after_render(OSWindow *os_window, double pixels) { + // second pass + glBindFramebuffer(GL_FRAMEBUFFER, 0); // back to default + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + + //printf("%f\n", pixels); + bind_program(SCROLL_PROGRAM); + glUniform1f(glGetUniformLocation(program_id(SCROLL_PROGRAM), "offset"), pixels); + glBindVertexArray(quadVAO); + glBindTexture(GL_TEXTURE_2D, os_window->scroll_texture_id); + glDrawArrays(GL_TRIANGLES, 0, 6); +} + #define CELL_BUFFERS enum { cell_data_buffer, selection_buffer, uniform_buffer }; ssize_t @@ -315,11 +375,17 @@ cell_prepare_to_render(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, GLfloa ensure_sprite_map(fonts_data); + if (screen->pixel_scroll_changed) { + screen->pixel_scroll_changed = false; + changed = true; + } + bool cursor_pos_changed = screen->cursor->x != screen->last_rendered.cursor_x || screen->cursor->y != screen->last_rendered.cursor_y; bool disable_ligatures = screen->disable_ligatures == DISABLE_LIGATURES_CURSOR; if (screen->reload_all_gpu_data || screen->scroll_changed || screen->is_dirty || (disable_ligatures && cursor_pos_changed)) { + screen->render_not_only_pixel_scroll = true; sz = sizeof(GPUCell) * screen->lines * screen->columns; address = alloc_and_map_vao_buffer(vao_idx, sz, cell_data_buffer, GL_STREAM_DRAW, GL_WRITE_ONLY); screen_update_cell_data(screen, address, fonts_data, disable_ligatures && cursor_pos_changed); @@ -333,6 +399,7 @@ cell_prepare_to_render(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, GLfloa } if (screen->reload_all_gpu_data || screen_is_selection_dirty(screen)) { + screen->render_not_only_pixel_scroll = true; sz = screen->lines * screen->columns; address = alloc_and_map_vao_buffer(vao_idx, sz, selection_buffer, GL_STREAM_DRAW, GL_WRITE_ONLY); screen_apply_selection(screen, address, sz); @@ -341,6 +408,7 @@ cell_prepare_to_render(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, GLfloa } if (gvao_idx && grman_update_layers(screen->grman, screen->scrolled_by, xstart, ystart, dx, dy, screen->columns, screen->lines, screen->cell_size)) { + screen->render_not_only_pixel_scroll = true; send_graphics_data_to_gpu(screen->grman->count, gvao_idx, screen->grman->render_data); changed = true; } @@ -808,7 +876,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(SCROLL_PROGRAM); C(GLSL_VERSION); C(GL_VERSION); C(GL_VENDOR); diff --git a/kitty/state.c b/kitty/state.c index 6577160c72b..2403271ec47 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -314,6 +314,7 @@ destroy_os_window_item(OSWindow *w) { } Py_CLEAR(w->window_title); Py_CLEAR(w->tab_bar_render_data.screen); if (w->offscreen_texture_id) free_texture(&w->offscreen_texture_id); + if (w->scroll_texture_id) free_texture(&w->scroll_texture_id); if (w->offscreen_framebuffer) free_framebuffer(&w->offscreen_framebuffer); remove_vao(w->tab_bar_render_data.vao_idx); remove_vao(w->gvao_idx); diff --git a/kitty/state.h b/kitty/state.h index ce7f3dc9874..1cc8c84c7a6 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -170,7 +170,7 @@ typedef struct { bool viewport_size_dirty, viewport_updated_at_least_once; LiveResizeInfo live_resize; bool has_pending_resizes, is_semi_transparent, shown_once, is_damaged; - uint32_t offscreen_texture_id; + uint32_t offscreen_texture_id, scroll_texture_id; unsigned int clear_count; color_type last_titlebar_color; float background_opacity; @@ -235,6 +235,9 @@ OSWindow* add_os_window(void); OSWindow* current_os_window(void); void os_window_regions(OSWindow*, Region *main, Region *tab_bar); bool drag_scroll(Window *, OSWindow*); +void setup_scroll(OSWindow *os_window); +void before_render(void); +void after_render(OSWindow *os_window, double pixels); 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, color_type, unsigned int, bool, OSWindow *w); ssize_t create_cell_vao(void); ssize_t create_graphics_vao(void); @@ -242,7 +245,7 @@ ssize_t create_border_vao(void); bool send_cell_data_to_gpu(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *); void draw_cells(ssize_t, ssize_t, float, float, float, float, Screen *, OSWindow *, bool, bool); void draw_centered_alpha_mask(OSWindow *w, size_t screen_width, size_t screen_height, size_t width, size_t height, uint8_t *canvas); -void update_surface_size(int, int, uint32_t); +void update_surface_size(int, int, uint32_t, uint32_t); void free_texture(uint32_t*); void free_framebuffer(uint32_t*); void send_image_to_gpu(uint32_t*, const void*, int32_t, int32_t, bool, bool, bool, RepeatStrategy); diff --git a/kitty/window.py b/kitty/window.py index 44c2dc7c85e..0b5e58ad39e 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -21,7 +21,7 @@ from .fast_data_types import ( BGIMAGE_PROGRAM, BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CSI, DCS, DECORATION, DIM, - GRAPHICS_ALPHA_MASK_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, + GRAPHICS_ALPHA_MASK_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, SCROLL_PROGRAM, MARK, MARK_MASK, OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, STRIKETHROUGH, TINT_PROGRAM, Screen, add_window, cell_size_for_window, compile_program, get_boss, get_clipboard_string, init_cell_program, @@ -146,6 +146,14 @@ def __call__(self, semi_transparent: bool = False) -> None: compile_program(TINT_PROGRAM, v, f) init_cell_program() + v, f = load_shaders('scroll') + for which, p in { + 'SIMPLE': SCROLL_PROGRAM, + }.items(): + ff = f.replace('ALPHA_TYPE', which) + compile_program(p, v, ff) + init_cell_program() + load_shader_programs = LoadShaderPrograms()