mirror of
https://github.com/kovidgoyal/kitty
synced 2026-06-08 14:18:26 +02:00
Sync to monitor refreshes by default
Prevents tearing while scrolling. See #318 Reduce draw calls while processing mouse move events to make latency while selecting with the mouse acceptable. Also add a config option to turn off monitor syncing, so people with keyboard repeat rates higher than their monitor's refresh rate can use it.
This commit is contained in:
@@ -25,8 +25,8 @@ version 0.8.0 [future]
|
|||||||
variation presentation selector.
|
variation presentation selector.
|
||||||
|
|
||||||
- Prevent video tearing during high speed scrolling by syncing draws
|
- Prevent video tearing during high speed scrolling by syncing draws
|
||||||
to the monitor's refresh rate (only works if supported by the graphics
|
to the monitor's refresh rate. There is a new configuration option to
|
||||||
drivers).
|
control this ``sync_to_monitor``.
|
||||||
|
|
||||||
- Add some non standard terminfo capabilities used by neovim and tmux.
|
- Add some non standard terminfo capabilities used by neovim and tmux.
|
||||||
|
|
||||||
|
|||||||
@@ -351,6 +351,8 @@ smoothness.
|
|||||||
There are two parameters you can tune to adjust the performance. ``repaint_delay``
|
There are two parameters you can tune to adjust the performance. ``repaint_delay``
|
||||||
and ``input_delay``. These control the artificial delays introduced into the
|
and ``input_delay``. These control the artificial delays introduced into the
|
||||||
render loop to reduce CPU usage. See the link:kitty/kitty.conf[config file] for details.
|
render loop to reduce CPU usage. See the link:kitty/kitty.conf[config file] for details.
|
||||||
|
See also the ``sync_to_monitor`` option to further decrease latency at the cost
|
||||||
|
of some link:https://en.wikipedia.org/wiki/Screen_tearing[tearing] while scrolling.
|
||||||
|
|
||||||
You can generate detailed per-function performance data using
|
You can generate detailed per-function performance data using
|
||||||
link:https://github.com/gperftools/gperftools[gperftools]. Build kitty with
|
link:https://github.com/gperftools/gperftools[gperftools]. Build kitty with
|
||||||
|
|||||||
@@ -591,6 +591,7 @@ prepare_to_render_os_window(OSWindow *os_window, double now, unsigned int *activ
|
|||||||
if (is_active_window) {
|
if (is_active_window) {
|
||||||
*active_window_id = w->id;
|
*active_window_id = w->id;
|
||||||
collect_cursor_info(&WD.screen->cursor_render_info, w, now, os_window);
|
collect_cursor_info(&WD.screen->cursor_render_info, w, now, os_window);
|
||||||
|
if (w->cursor_visible_at_last_render != WD.screen->cursor_render_info.is_visible) needs_render = true;
|
||||||
update_window_title(w, os_window);
|
update_window_title(w, os_window);
|
||||||
} else WD.screen->cursor_render_info.is_visible = false;
|
} else WD.screen->cursor_render_info.is_visible = false;
|
||||||
if (send_cell_data_to_gpu(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen, os_window)) needs_render = true;
|
if (send_cell_data_to_gpu(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen, os_window)) needs_render = true;
|
||||||
@@ -618,6 +619,7 @@ render_os_window(OSWindow *os_window, double now, unsigned int active_window_id)
|
|||||||
double bell_left = global_state.opts.visual_bell_duration - (now - WD.screen->start_visual_bell_at);
|
double bell_left = global_state.opts.visual_bell_duration - (now - WD.screen->start_visual_bell_at);
|
||||||
set_maximum_wait(bell_left);
|
set_maximum_wait(bell_left);
|
||||||
}
|
}
|
||||||
|
w->cursor_visible_at_last_render = WD.screen->cursor_render_info.is_visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
swap_window_buffers(os_window);
|
swap_window_buffers(os_window);
|
||||||
@@ -640,7 +642,7 @@ render(double now) {
|
|||||||
for (size_t i = 0; i < global_state.num_os_windows; i++) {
|
for (size_t i = 0; i < global_state.num_os_windows; i++) {
|
||||||
OSWindow *w = global_state.os_windows + i;
|
OSWindow *w = global_state.os_windows + i;
|
||||||
if (!w->num_tabs || !should_os_window_be_rendered(w)) continue;
|
if (!w->num_tabs || !should_os_window_be_rendered(w)) continue;
|
||||||
bool needs_render = w->is_focused || w->is_damaged;
|
bool needs_render = w->is_damaged;
|
||||||
make_os_window_context_current(w);
|
make_os_window_context_current(w);
|
||||||
if (w->viewport_size_dirty) {
|
if (w->viewport_size_dirty) {
|
||||||
w->clear_count = 0;
|
w->clear_count = 0;
|
||||||
|
|||||||
@@ -271,6 +271,7 @@ type_map = {
|
|||||||
'rectangle_select_modifiers': to_modifiers,
|
'rectangle_select_modifiers': to_modifiers,
|
||||||
'repaint_delay': positive_int,
|
'repaint_delay': positive_int,
|
||||||
'input_delay': positive_int,
|
'input_delay': positive_int,
|
||||||
|
'sync_to_monitor': to_bool,
|
||||||
'window_border_width': positive_float,
|
'window_border_width': positive_float,
|
||||||
'window_margin_width': positive_float,
|
'window_margin_width': positive_float,
|
||||||
'window_padding_width': positive_float,
|
'window_padding_width': positive_float,
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
|
|||||||
glfwMakeContextCurrent(glfw_window);
|
glfwMakeContextCurrent(glfw_window);
|
||||||
if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y);
|
if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y);
|
||||||
current_os_window_ctx = glfw_window;
|
current_os_window_ctx = glfw_window;
|
||||||
glfwSwapInterval(0); // a value of 1 makes mouse selection laggy
|
glfwSwapInterval(OPT(sync_to_monitor) ? 1 : 0); // a value of 1 makes mouse selection laggy
|
||||||
if (is_first_window) {
|
if (is_first_window) {
|
||||||
set_dpi_from_os_window(NULL);
|
set_dpi_from_os_window(NULL);
|
||||||
gl_init();
|
gl_init();
|
||||||
|
|||||||
@@ -127,7 +127,9 @@ initial_window_height 400
|
|||||||
|
|
||||||
# Delay (in milliseconds) between screen updates. Decreasing it, increases
|
# Delay (in milliseconds) between screen updates. Decreasing it, increases
|
||||||
# frames-per-second (FPS) at the cost of more CPU usage. The default value
|
# frames-per-second (FPS) at the cost of more CPU usage. The default value
|
||||||
# yields ~100 FPS which is more than sufficient for most uses.
|
# yields ~100 FPS which is more than sufficient for most uses. Note that to
|
||||||
|
# actually achieve 100FPS you have to either set sync_to_monitor to no or use a
|
||||||
|
# monitor with a high refresh rate.
|
||||||
repaint_delay 10
|
repaint_delay 10
|
||||||
|
|
||||||
# Delay (in milliseconds) before input from the program running in the terminal
|
# Delay (in milliseconds) before input from the program running in the terminal
|
||||||
@@ -137,6 +139,13 @@ repaint_delay 10
|
|||||||
# screen updates will be drawn.
|
# screen updates will be drawn.
|
||||||
input_delay 3
|
input_delay 3
|
||||||
|
|
||||||
|
# Sync screen updates to the refresh rate of the monitor. This prevents
|
||||||
|
# tearing (https://en.wikipedia.org/wiki/Screen_tearing) when scrolling. However,
|
||||||
|
# it limits the rendering speed to the refresh rate of your monitor. With a
|
||||||
|
# very high speed mouse/high keyboard repeat rate, you may notice some slight input latency.
|
||||||
|
# If so, set this to no.
|
||||||
|
sync_to_monitor yes
|
||||||
|
|
||||||
# Visual bell duration. Flash the screen when a bell occurs for the specified number of
|
# Visual bell duration. Flash the screen when a bell occurs for the specified number of
|
||||||
# seconds. Set to zero to disable.
|
# seconds. Set to zero to disable.
|
||||||
visual_bell_duration 0.0
|
visual_bell_duration 0.0
|
||||||
|
|||||||
@@ -349,6 +349,7 @@ PYWRAP1(set_options) {
|
|||||||
S(background, color_as_int);
|
S(background, color_as_int);
|
||||||
S(repaint_delay, repaint_delay);
|
S(repaint_delay, repaint_delay);
|
||||||
S(input_delay, repaint_delay);
|
S(input_delay, repaint_delay);
|
||||||
|
S(sync_to_monitor, PyObject_IsTrue);
|
||||||
S(macos_option_as_alt, PyObject_IsTrue);
|
S(macos_option_as_alt, PyObject_IsTrue);
|
||||||
S(macos_hide_titlebar, PyObject_IsTrue);
|
S(macos_hide_titlebar, PyObject_IsTrue);
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ typedef struct {
|
|||||||
float background_opacity;
|
float background_opacity;
|
||||||
float inactive_text_alpha;
|
float inactive_text_alpha;
|
||||||
Edge tab_bar_edge;
|
Edge tab_bar_edge;
|
||||||
|
bool sync_to_monitor;
|
||||||
} Options;
|
} Options;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -55,7 +56,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
id_type id;
|
id_type id;
|
||||||
bool visible;
|
bool visible, cursor_visible_at_last_render;
|
||||||
PyObject *title;
|
PyObject *title;
|
||||||
ScreenRenderData render_data;
|
ScreenRenderData render_data;
|
||||||
unsigned int mouse_cell_x, mouse_cell_y;
|
unsigned int mouse_cell_x, mouse_cell_y;
|
||||||
@@ -108,10 +109,7 @@ typedef struct {
|
|||||||
bool is_key_pressed[MAX_KEY_COUNT];
|
bool is_key_pressed[MAX_KEY_COUNT];
|
||||||
bool viewport_size_dirty;
|
bool viewport_size_dirty;
|
||||||
double last_resize_event_at;
|
double last_resize_event_at;
|
||||||
bool has_pending_resizes;
|
bool has_pending_resizes, is_semi_transparent, shown_once, is_damaged;
|
||||||
bool is_semi_transparent;
|
|
||||||
bool shown_once;
|
|
||||||
bool is_damaged;
|
|
||||||
uint32_t offscreen_texture_id;
|
uint32_t offscreen_texture_id;
|
||||||
unsigned int clear_count;
|
unsigned int clear_count;
|
||||||
} OSWindow;
|
} OSWindow;
|
||||||
|
|||||||
Reference in New Issue
Block a user