misc fixes for decoration rendering

This commit is contained in:
Kovid Goyal 2024-12-15 14:22:54 +05:30
parent c3361cd26b
commit b249fba93d
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
6 changed files with 41 additions and 35 deletions

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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

View file

@ -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]);

View file

@ -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()

View file

@ -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)) {