From b249fba93de27e63bc74f6ed571e427f5ffe93ec Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 15 Dec 2024 14:22:54 +0530 Subject: [PATCH] misc fixes for decoration rendering --- kitty/cell_vertex.glsl | 6 ++--- kitty/decorations.c | 2 +- kitty/fast_data_types.pyi | 1 + kitty/fonts.c | 47 ++++++++++++++++++++++----------------- kitty/fonts/render.py | 4 ++-- kitty/shaders.c | 16 ++++++------- 6 files changed, 41 insertions(+), 35 deletions(-) diff --git a/kitty/cell_vertex.glsl b/kitty/cell_vertex.glsl index 4e98d50a7..eb0b85c5d 100644 --- a/kitty/cell_vertex.glsl +++ b/kitty/cell_vertex.glsl @@ -100,9 +100,9 @@ vec3 to_color(uint c, uint defval) { uvec3 to_sprite_coords(uint idx) { uint sprites_per_page = sprites_xnum * sprites_ynum; uint z = idx / sprites_per_page; - uint num_on_last_page = idx % sprites_per_page; + uint num_on_last_page = idx - sprites_per_page * z; uint y = num_on_last_page / sprites_xnum; - uint x = num_on_last_page % sprites_xnum; + uint x = num_on_last_page - sprites_xnum * y; return uvec3(x, y, z); } @@ -118,7 +118,7 @@ uint read_sprite_decorations_idx() { int idx = int(sprite_idx[0] & SPRITE_INDEX_MASK); ivec2 sz = textureSize(sprite_decorations_map, 0); int y = idx / sz[0]; - int x = idx % sz[0]; + int x = idx - y * sz[0]; return texelFetch(sprite_decorations_map, ivec2(x, y), 0).r; } diff --git a/kitty/decorations.c b/kitty/decorations.c index 4f75fd887..dae32f403 100644 --- a/kitty/decorations.c +++ b/kitty/decorations.c @@ -195,7 +195,7 @@ add_beam_cursor(uint8_t *buf, FontCellMetrics fcm, double dpi_x) { DecorationGeometry add_underline_cursor(uint8_t *buf, FontCellMetrics fcm, double dpi_y) { DecorationGeometry ans = {0}; - ans.top = horz(buf, true, OPT(cursor_underline_thickness), dpi_y, fcm); + ans.top = horz(buf, false, OPT(cursor_underline_thickness), dpi_y, fcm); ans.height = fcm.cell_height - ans.top; return ans; } diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi index b7d70da54..80c3279da 100644 --- a/kitty/fast_data_types.pyi +++ b/kitty/fast_data_types.pyi @@ -1213,6 +1213,7 @@ class Screen: def test_create_write_buffer(self) -> memoryview: ... def test_commit_write_buffer(self, inp: memoryview, output: memoryview) -> int: ... def test_parse_written_data(self, dump_callback: None = None) -> None: ... + def hyperlink_for_id(self, hyperlink_id: int) -> str: ... def cursor_at_prompt(self) -> bool: pass diff --git a/kitty/fonts.c b/kitty/fonts.c index a87214be5..211c662f8 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -125,8 +125,27 @@ static size_t num_font_groups = 0; static id_type font_group_id_counter = 0; static void initialize_font_group(FontGroup *fg); +static void +display_rgba_data(const pixel *b, unsigned width, unsigned height) { + RAII_PyObject(m, PyImport_ImportModule("kitty.fonts.render")); + RAII_PyObject(f, PyObject_GetAttrString(m, "show")); + RAII_PyObject(data, PyMemoryView_FromMemory((char*)b, width * height * sizeof(b[0]), PyBUF_READ)); + RAII_PyObject(ret, PyObject_CallFunction(f, "OII", data, width, height)); + if (PyErr_Occurred()) PyErr_Print(); +} + +static void +dump_sprite(pixel *b, unsigned width, unsigned height) { + for (unsigned y = 0; y < height; y++) { + pixel *p = b + y * width; + for (unsigned x = 0; x < width; x++) printf("%d ", p[x] != 0); + printf("\n"); + } +} + static void python_send_to_gpu(FontGroup *fg, sprite_index idx, pixel *buf) { + if (0) dump_sprite(buf, fg->fcm.cell_width, fg->fcm.cell_height); unsigned int x, y, z; sprite_index_to_pos(idx, fg->sprite_tracker.xnum, fg->sprite_tracker.ynum, &x, &y, &z); const size_t sprite_size = fg->fcm.cell_width * fg->fcm.cell_height; @@ -137,6 +156,7 @@ python_send_to_gpu(FontGroup *fg, sprite_index idx, pixel *buf) { static void current_send_sprite_to_gpu(FontGroup *fg, sprite_index idx, pixel *buf, sprite_index decorations_idx) { + if (0) { printf("Sprite: %u dec_idx: %u\n", idx, decorations_idx); display_rgba_data(buf, fg->fcm.cell_width, fg->fcm.cell_height); printf("\n"); } if (python_send_to_gpu_impl) { python_send_to_gpu(fg, idx, buf); return; } send_sprite_to_gpu((FONTS_DATA_HANDLE)fg, idx, buf, decorations_idx); } @@ -297,7 +317,7 @@ do_increment(FontGroup *fg, int *error) { } static uint32_t -current_sprite_index(GPUSpriteTracker *sprite_tracker) { +current_sprite_index(const GPUSpriteTracker *sprite_tracker) { return sprite_tracker->z * (sprite_tracker->xnum * sprite_tracker->ynum) + sprite_tracker->y * sprite_tracker->xnum + sprite_tracker->x; } @@ -869,19 +889,6 @@ extract_cell_region(Canvas *canvas, unsigned i, Region *src, const Region *dest, return ans; } -__attribute__((unused)) -static void -dump_sprite(pixel *b, unsigned width, unsigned height, bool actual_pixel_values) { - for (unsigned y = 0; y < height; y++) { - pixel *p = b + y * width; - for (unsigned x = 0; x < width; x++) { - if (actual_pixel_values) printf("%08x ", p[x]); - else printf("%d ", p[x] != 0); - } - printf("\n"); - } -} - static void set_cell_sprite(GPUCell *cell, const SpritePosition *sp) { cell->sprite_idx = sp->idx & 0x7fffffff; @@ -890,6 +897,7 @@ set_cell_sprite(GPUCell *cell, const SpritePosition *sp) { static void render_scaled_decoration(FontCellMetrics unscaled_metrics, FontCellMetrics scaled_metrics, uint8_t *alpha_mask, pixel *output, Region src, Region dest) { + memset(output, 0, unscaled_metrics.cell_width * unscaled_metrics.cell_height * sizeof(output[0])); pixel col = 0xffffff00; unsigned src_limit = MIN(scaled_metrics.cell_height, src.bottom), dest_limit = MIN(unscaled_metrics.cell_height, dest.bottom); unsigned cell_width = MIN(scaled_metrics.cell_width, unscaled_metrics.cell_width); @@ -906,7 +914,7 @@ render_decorations(FontGroup *fg, Region src, Region dest, FontCellMetrics scale const FontCellMetrics unscaled_metrics = fg->fcm; scaled_metrics.cell_width = unscaled_metrics.cell_width; RAII_ALLOC(uint8_t, alpha_mask, malloc(scaled_metrics.cell_height * scaled_metrics.cell_width)); - RAII_ALLOC(pixel, buf, malloc(unscaled_metrics.cell_width * (unscaled_metrics.cell_height + 1) * sizeof(pixel))); + RAII_ALLOC(pixel, buf, malloc(unscaled_metrics.cell_width * unscaled_metrics.cell_height * sizeof(pixel))); if (!alpha_mask || !buf) fatal("Out of memory"); int error = 0; sprite_index idx = current_sprite_index(&fg->sprite_tracker); @@ -914,7 +922,6 @@ render_decorations(FontGroup *fg, Region src, Region dest, FontCellMetrics scale #define do_one(call) \ memset(alpha_mask, 0, scaled_metrics.cell_width * scaled_metrics.cell_height * sizeof(alpha_mask[0])); \ call; \ - memset(buf, 0, unscaled_metrics.cell_width * unscaled_metrics.cell_height * sizeof(buf[0])); \ render_scaled_decoration(unscaled_metrics, scaled_metrics, alpha_mask, buf, src, dest); \ current_send_sprite_to_gpu(fg, current_sprite_index(&fg->sprite_tracker), buf, 0); \ increment_sprite_index; @@ -1000,7 +1007,7 @@ render_box_cell(FontGroup *fg, RunFont rf, CPUCell *cpu_cell, GPUCell *gpu_cell, width *= num_glyphs; Region src = { .right = width, .bottom = height }, dest = src; render_alpha_mask(alpha_mask, fg->canvas.buf, &src, &dest, width, width, 0xffffff); - /*printf("Rendered char sz: (%u, %u)\n", width, height); dump_sprite(fg->canvas.buf, width, height, false);*/ + /*printf("Rendered char sz: (%u, %u)\n", width, height); dump_sprite(fg->canvas.buf, width, height);*/ if (scale == 1.f && rf.scale == 1 && !rf.subscale_n) { sp[0]->rendered = true; current_send_sprite_to_gpu(fg, sp[0]->idx, fg->canvas.buf, index_for_decorations(fg, rf, src, dest, scaled_metrics)); @@ -1009,7 +1016,7 @@ render_box_cell(FontGroup *fg, RunFont rf, CPUCell *cpu_cell, GPUCell *gpu_cell, /*printf("width: %u height: %u unscaled_cell_width: %u unscaled_cell_height: %u src.top: %u src.bottom: %u rf.scale: %u\n", width, height, fg->fcm.cell_width, fg->fcm.cell_height, src.top, src.bottom, rf.scale);*/ for (unsigned i = 0; i < rf.scale; i++) { pixel *b = extract_cell_region(&fg->canvas, i, &src, &dest, width, fg->fcm); - /*printf("Sprite %u: pos: (%u, %u, %u) sz: (%u, %u)\n", i, sp[i]->x, sp[i]->y, sp[i]->z, fg->fcm.cell_width, fg->fcm.cell_height); dump_sprite(b, fg->fcm.cell_width, fg->fcm.cell_height, false);*/ + /*printf("Sprite %u: pos: (%u, %u, %u) sz: (%u, %u)\n", i, sp[i]->x, sp[i]->y, sp[i]->z, fg->fcm.cell_width, fg->fcm.cell_height); dump_sprite(b, fg->fcm.cell_width, fg->fcm.cell_height);*/ sp[i]->rendered = true; current_send_sprite_to_gpu(fg, sp[i]->idx, b, index_for_decorations(fg, rf, src, dest, scaled_metrics)); } @@ -1087,7 +1094,7 @@ render_group( if (is_only_filled_boxes) { // special case rendering of █ for tests render_filled_sprite(fg->canvas.buf, num_glyphs, scaled_metrics, num_scaled_cells); was_colored = false; - /*dump_sprite(fg->canvas.buf, scaled_metrics.cell_width * num_scaled_cells, scaled_metrics.cell_height, false);*/ + /*dump_sprite(fg->canvas.buf, scaled_metrics.cell_width * num_scaled_cells, scaled_metrics.cell_height);*/ } else render_glyphs_in_cells(font->face, font->bold, font->italic, info, positions, num_glyphs, fg->canvas.buf, scaled_metrics.cell_width, scaled_metrics.cell_height, num_scaled_cells, scaled_metrics.baseline, &was_colored, (FONTS_DATA_HANDLE)fg, center_glyph); if (PyErr_Occurred()) PyErr_Print(); @@ -1115,7 +1122,7 @@ render_group( pixel *b = extract_cell_region(&fg->canvas, i, &src, &dest, scaled_metrics.cell_width * num_scaled_cells, unscaled_metrics); /*printf("cell %u src -> dest: (%u %u) -> (%u %u)\n", i, src.left, src.right, dest.left, dest.right);*/ current_send_sprite_to_gpu(fg, sp[i]->idx, b, index_for_decorations(fg, rf, src, dest, scaled_metrics)); - /*dump_sprite(b, unscaled_metrics.cell_width, unscaled_metrics.cell_height, false);*/ + /*dump_sprite(b, unscaled_metrics.cell_width, unscaled_metrics.cell_height);*/ sp[i]->rendered = true; sp[i]->colored = was_colored; } set_cell_sprite(gpu_cells + i, sp[i]); diff --git a/kitty/fonts/render.py b/kitty/fonts/render.py index 213115ca9..07ec36177 100644 --- a/kitty/fonts/render.py +++ b/kitty/fonts/render.py @@ -293,7 +293,7 @@ def shape_string( return test_shape(line, path) -def show(rgba_data: bytes, width: int, height: int, fmt: int = 32) -> None: +def show(rgba_data: Union[bytes, memoryview], width: int, height: int, fmt: int = 32) -> None: from base64 import standard_b64encode from kittens.tui.images import GraphicsCommand @@ -305,12 +305,12 @@ def show(rgba_data: bytes, width: int, height: int, fmt: int = 32) -> None: cmd.s = width cmd.v = height + sys.stdout.flush() while data: chunk, data = data[:4096], data[4096:] cmd.m = 1 if data else 0 sys.stdout.buffer.write(cmd.serialize(chunk)) cmd.clear() - sys.stdout.flush() sys.stdout.buffer.flush() diff --git a/kitty/shaders.c b/kitty/shaders.c index 4e65970fe..28bf78dc4 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -205,16 +205,14 @@ send_sprite_to_gpu(FONTS_DATA_HANDLE fg, sprite_index idx, pixel *buf, sprite_in SpriteMap *sprite_map = (SpriteMap*)fg->sprite_map; unsigned int xnum, ynum, znum, x, y, z; #define dm (sprite_map->decorations_map) + if (idx >= dm.count) dm.count = idx + 1; realloc_sprite_decorations_texture_if_needed(fg); - if (idx >= dm.count) { - dm.count = idx + 1; - div_t d = div(idx, dm.width); - x = d.rem; y = d.quot; - glActiveTexture(GL_TEXTURE0 + SPRITE_DECORATIONS_MAP_UNIT); - glBindTexture(GL_TEXTURE_2D, dm.texture_id); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &decoration_idx); - } + div_t d = div(idx, dm.width); + x = d.rem; y = d.quot; + glActiveTexture(GL_TEXTURE0 + SPRITE_DECORATIONS_MAP_UNIT); + glBindTexture(GL_TEXTURE_2D, dm.texture_id); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, 1, 1, GL_RED_INTEGER, GL_UNSIGNED_INT, &decoration_idx); #undef dm sprite_tracker_current_layout(fg, &xnum, &ynum, &znum); if ((int)znum >= sprite_map->last_num_of_layers || (znum == 0 && (int)ynum > sprite_map->last_ynum)) {