Fix graphics being scaled during live resize

This commit is contained in:
Kovid Goyal 2023-06-21 06:17:35 +05:30
parent ae3fdcd64d
commit a4373ec8b4
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 40 additions and 6 deletions

View file

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

View file

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

View file

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

View file

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