diff --git a/kitty/shaders.c b/kitty/shaders.c index df7d669bb..1e5d4c8fd 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -1400,18 +1400,28 @@ start_os_window_rendering(OSWindow *os_window, Tab *tab) { // note that during live resize rendering is done in layers if (os_window->live_resize.in_progress) blank_os_window(os_window); if (os_window->needs_layers) { - if (os_window->indirect_output.width != os_window->viewport_width || os_window->indirect_output.height != os_window->viewport_height) { - if (os_window->indirect_output.texture_id) free_texture(&os_window->indirect_output.texture_id); - if (os_window->indirect_output.framebuffer_id) free_framebuffer(&os_window->indirect_output.framebuffer_id); + // Ensure the global shared texture is large enough for this window + if (global_state.layers_render_texture.width < os_window->viewport_width || + global_state.layers_render_texture.height < os_window->viewport_height) { + if (global_state.layers_render_texture.texture_id) free_texture(&global_state.layers_render_texture.texture_id); + if (global_state.layers_render_texture.framebuffer_id) free_framebuffer(&global_state.layers_render_texture.framebuffer_id); + unsigned new_w = (unsigned)MAX(global_state.layers_render_texture.width, os_window->viewport_width); + unsigned new_h = (unsigned)MAX(global_state.layers_render_texture.height, os_window->viewport_height); + setup_texture_as_render_target(new_w, new_h, &global_state.layers_render_texture.texture_id, &global_state.layers_render_texture.framebuffer_id); + global_state.layers_render_texture.width = (int)new_w; + global_state.layers_render_texture.height = (int)new_h; + global_state.layers_render_texture.texture_generation++; } - if (os_window->indirect_output.texture_id == 0) { - os_window->indirect_output.width = os_window->viewport_width; - os_window->indirect_output.height = os_window->viewport_height; - setup_texture_as_render_target((unsigned) os_window->viewport_width, (unsigned)os_window->viewport_height, &os_window->indirect_output.texture_id, &os_window->indirect_output.framebuffer_id); + // Create per-window framebuffer if needed and attach the global texture to it + if (!os_window->indirect_output.framebuffer_id) glGenFramebuffers(1, &os_window->indirect_output.framebuffer_id); + if (os_window->indirect_output.attached_texture_generation != global_state.layers_render_texture.texture_generation) { + bind_framebuffer_for_output(os_window->indirect_output.framebuffer_id); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, global_state.layers_render_texture.texture_id, 0); + os_window->indirect_output.attached_texture_generation = global_state.layers_render_texture.texture_generation; } set_framebuffer_to_use_for_output(os_window->indirect_output.framebuffer_id); bind_framebuffer_for_output(0); - save_viewport_using_bottom_left_origin(0, 0, os_window->indirect_output.width, os_window->indirect_output.height); + save_viewport_using_bottom_left_origin(0, 0, os_window->viewport_width, os_window->viewport_height); clear_current_framebuffer(); draw_bg_image(os_window, tab); } @@ -1425,8 +1435,10 @@ stop_os_window_rendering(OSWindow *os_window, Tab *tab, Window *active_window) { bind_framebuffer_for_output(0); bind_program(BLIT_PROGRAM); glActiveTexture(GL_TEXTURE0 + GRAPHICS_UNIT); - glBindTexture(GL_TEXTURE_2D, os_window->indirect_output.texture_id); - glUniform4f(blit_program_layout.uniforms.src_rect, 0, 1, 1, 0); + glBindTexture(GL_TEXTURE_2D, global_state.layers_render_texture.texture_id); + float sx = global_state.layers_render_texture.width > 0 ? (float)os_window->viewport_width / (float)global_state.layers_render_texture.width : 1.f; + float sy = global_state.layers_render_texture.height > 0 ? (float)os_window->viewport_height / (float)global_state.layers_render_texture.height : 1.f; + glUniform4f(blit_program_layout.uniforms.src_rect, 0, sy, sx, 0); glUniform4f(blit_program_layout.uniforms.dest_rect, -1, 1, 1, -1); restore_viewport(); if (os_window->live_resize.in_progress) save_viewport_using_top_left_origin( diff --git a/kitty/state.c b/kitty/state.c index 56ef919d5..5a5927602 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -491,7 +491,6 @@ destroy_os_window_item(OSWindow *w) { free(w->tabs); w->tabs = NULL; free_bgimage(&w->bgimage, true); zero_at_ptr(&w->bgimage); - if (w->indirect_output.texture_id) free_texture(&w->indirect_output.texture_id); if (w->indirect_output.framebuffer_id) free_framebuffer(&w->indirect_output.framebuffer_id); } @@ -507,6 +506,11 @@ remove_os_window(id_type os_window_id) { REMOVER(global_state.os_windows, os_window_id, global_state.num_os_windows, destroy_os_window_item, global_state.capacity); END_WITH_OS_WINDOW_REFS update_os_window_references(); + if (global_state.num_os_windows == 0) { + if (global_state.layers_render_texture.texture_id) free_texture(&global_state.layers_render_texture.texture_id); + if (global_state.layers_render_texture.framebuffer_id) free_framebuffer(&global_state.layers_render_texture.framebuffer_id); + global_state.layers_render_texture.width = 0; global_state.layers_render_texture.height = 0; + } } return found; } diff --git a/kitty/state.h b/kitty/state.h index b962994ff..0fa8a69d8 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -312,8 +312,7 @@ typedef struct OSWindow { Tab *tabs; BackgroundImage *bgimage; struct { - uint32_t texture_id, framebuffer_id; - int width, height; + uint32_t framebuffer_id, attached_texture_generation; } indirect_output; unsigned int active_tab, num_tabs, capacity, last_active_tab, last_num_tabs, last_active_window_id; bool focused_at_last_render, needs_render, needs_layers; @@ -403,6 +402,10 @@ typedef struct GlobalState { id_type id; bool drag_started; double x, y; } tab_being_dragged; + struct { + uint32_t texture_id, framebuffer_id, texture_generation; + int width, height; + } layers_render_texture; } GlobalState; extern GlobalState global_state;