From a4373ec8b4edae26e1642d034f234c8356250213 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 21 Jun 2023 06:17:35 +0530 Subject: [PATCH] Fix graphics being scaled during live resize --- kitty/graphics.c | 16 +++++++++++++++- kitty/graphics.h | 1 + kitty/shaders.c | 27 +++++++++++++++++++++++---- kitty/state.h | 2 +- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/kitty/graphics.c b/kitty/graphics.c index 9b3e15448..dbfa0ae4a 100644 --- a/kitty/graphics.c +++ b/kitty/graphics.c @@ -907,9 +907,23 @@ set_vertex_data(ImageRenderData *rd, const ImageRef *ref, const ImageRect *dest_ #undef R } +void +scale_rendered_graphic(ImageRenderData *rd, float xstart, float ystart, float x_scale, float y_scale) { + float right = rd->vertices[2], left = rd->vertices[8 + 2], top = rd->vertices[3], bottom = rd->vertices[4 + 3]; + float width = right - left, height = bottom - top; + left = xstart + (left - xstart) * x_scale; + right = left + width * x_scale; + top = ystart + (top - ystart) * y_scale; + bottom = top + height * y_scale; + rd->vertices[0+2] = right; rd->vertices[4+2] = right; + rd->vertices[8+2] = left; rd->vertices[12+2] = left; + rd->vertices[0+3] = top; rd->vertices[12+3] = top; + rd->vertices[4+3] = bottom; rd->vertices[8+3] = bottom; +} + void gpu_data_for_image(ImageRenderData *ans, float left, float top, float right, float bottom) { - // x-axis is from -1 to 1, y axis is from 1 to -1 + // For dest rect: x-axis is from -1 to 1, y axis is from 1 to -1 static const ImageRef source_rect = { .src_rect = { .left=0, .top=0, .bottom=1, .right=1 }}; const ImageRef *ref = &source_rect; const ImageRect r = { .left = left, .right = right, .top = top, .bottom = bottom }; diff --git a/kitty/graphics.h b/kitty/graphics.h index d7683a79b..845c94156 100644 --- a/kitty/graphics.h +++ b/kitty/graphics.h @@ -172,3 +172,4 @@ void gpu_data_for_image(ImageRenderData *ans, float left, float top, float right bool png_from_file_pointer(FILE* fp, const char *path, uint8_t** data, unsigned int* width, unsigned int* height, size_t* sz); bool png_path_to_bitmap(const char *path, uint8_t** data, unsigned int* width, unsigned int* height, size_t* sz); bool scan_active_animations(GraphicsManager *self, const monotonic_t now, monotonic_t *minimum_gap, bool os_window_context_set); +void scale_rendered_graphic(ImageRenderData*, float xstart, float ystart, float x_scale, float y_scale); diff --git a/kitty/shaders.c b/kitty/shaders.c index 89513b2d4..847d276bd 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -281,9 +281,10 @@ static struct CellUniformData cell_uniform_data = {0, .prev_inactive_text_alpha= static void send_graphics_data_to_gpu(size_t image_count, ssize_t gvao_idx, const ImageRenderData *render_data) { - size_t sz = sizeof(GLfloat) * 16 * image_count; + const size_t num_of_floats_per_image = arraysz(render_data[0].vertices); + size_t sz = sizeof(GLfloat) * num_of_floats_per_image * image_count; GLfloat *a = alloc_and_map_vao_buffer(gvao_idx, sz, 0, GL_STREAM_DRAW, GL_WRITE_ONLY); - for (size_t i = 0; i < image_count; i++, a += 16) memcpy(a, render_data[i].vertices, sizeof(render_data[0].vertices)); + for (size_t i = 0; i < image_count; i++, a += num_of_floats_per_image) memcpy(a, render_data[i].vertices, sizeof(render_data[0].vertices)); unmap_vao_buffer(gvao_idx, 0); a = NULL; } @@ -938,6 +939,16 @@ get_visual_bell_intensity(Screen *screen) { return 0.0f; } +static void +scale_graphics_for_live_resize(Screen *screen, float xstart, float ystart, CellRenderData *crd, ssize_t gvao_idx) { + const size_t sz = screen->grman->count * sizeof(screen->grman->render_data[0]); + FREE_AFTER_FUNCTION ImageRenderData *changed = malloc(sz); + if (changed == NULL) fatal("Out of memory allocating temporary ImageRenderData* for live resize"); + memcpy(changed, screen->grman->render_data, sz); + for (size_t i = 0; i < screen->grman->count; i++) scale_rendered_graphic(changed + i, xstart, ystart, crd->x_ratio, crd->y_ratio); + send_graphics_data_to_gpu(screen->grman->count, gvao_idx, changed); +} + void draw_cells(ssize_t vao_idx, ssize_t gvao_idx, const ScreenRenderData *srd, OSWindow *os_window, bool is_active_window, bool can_be_focused, Window *window) { float x_ratio = 1., y_ratio = 1.; @@ -956,11 +967,13 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, const ScreenRenderData *srd, OSWin // The scissor limits below are calculated to ensure that they do not // overlap with the pixels outside the draw area. We can't use the actual pixel window dimensions // because of the mapping of opengl's float based co-ord system to pixels. - // for a test case (scissor is also used to blit framebuffer in draw_cells_interleaved_premult) run: + // for a test case (scissor is used to blit framebuffer in draw_cells_interleaved_premult) run: // kitty -o background=cyan -o background_opacity=0.7 -o cursor_blink_interval=0 -o window_margin_width=40 -o remember_initial_window_size=n -o initial_window_width=401 kitty +kitten icat --hold logo/kitty.png // Repeat incrementing window width by 1px each time over cursor_width number of pixels and see if any lines // appear at the borders of the content area -#define SCALE(w, x) ((GLfloat)(os_window->viewport_##w) * (GLfloat)(x)) + unsigned scissor_base_width = os_window->live_resize.in_progress ? os_window->live_resize.width : (unsigned)os_window->viewport_width; + unsigned scissor_base_height = os_window->live_resize.in_progress ? os_window->live_resize.height: (unsigned)os_window->viewport_height; +#define SCALE(w, x) ((GLfloat)(scissor_base_##w) * (GLfloat)(x)) /* printf("columns=%d dx=%f w=%f vw=%d vh=%d left=%f width=%f\n", screen->columns, dx, w, os_window->viewport_width, os_window->viewport_height, SCALE(width, (xstart + 1.f)/2.f), SCALE(width, w / 2.f)); */ crd.px.xstart = (GLint)roundf(SCALE(width, (crd.gl.xstart + 1.f)/2.f)); @@ -984,6 +997,11 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, const ScreenRenderData *srd, OSWin has_underlying_image = true; set_on_gpu_state(window->window_logo.instance, true); } else wl = NULL; + bool restore_graphics_render_data = false; + if (os_window->live_resize.in_progress && window->render_data.gvao_idx && screen->grman->count && (crd.x_ratio != 1 || crd.y_ratio != 1)) { + restore_graphics_render_data = true; + scale_graphics_for_live_resize(screen, srd->xstart, srd->ystart, &crd, window->render_data.gvao_idx); + } if (os_window->is_semi_transparent) { if (screen->grman->count || has_underlying_image) draw_cells_interleaved_premult( vao_idx, gvao_idx, screen, os_window, &crd, wl); @@ -1001,6 +1019,7 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, const ScreenRenderData *srd, OSWin if (window && screen->display_window_char) draw_window_number(os_window, screen, &crd, window); if (OPT(show_hyperlink_targets) && window && screen->current_hyperlink_under_mouse.id && !is_mouse_hidden(os_window)) draw_hyperlink_target(os_window, screen, &crd, window); + if (restore_graphics_render_data) send_graphics_data_to_gpu(screen->grman->count, window->render_data.gvao_idx, screen->grman->render_data); } // }}} diff --git a/kitty/state.h b/kitty/state.h index db3859e8c..843b30742 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -101,7 +101,7 @@ typedef struct WindowLogoRenderData { typedef struct { ssize_t vao_idx, gvao_idx; - float xstart, ystart, dx, dy, xratio, yratio; + float xstart, ystart, dx, dy; Screen *screen; } ScreenRenderData;