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:
Kovid Goyal 2018-02-20 09:38:00 +05:30
parent e6cb64baa5
commit 5a15f7e8ad
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
8 changed files with 23 additions and 10 deletions

View File

@ -25,8 +25,8 @@ version 0.8.0 [future]
variation presentation selector.
- Prevent video tearing during high speed scrolling by syncing draws
to the monitor's refresh rate (only works if supported by the graphics
drivers).
to the monitor's refresh rate. There is a new configuration option to
control this ``sync_to_monitor``.
- Add some non standard terminfo capabilities used by neovim and tmux.

View File

@ -351,6 +351,8 @@ smoothness.
There are two parameters you can tune to adjust the performance. ``repaint_delay``
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.
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
link:https://github.com/gperftools/gperftools[gperftools]. Build kitty with

View File

@ -591,6 +591,7 @@ prepare_to_render_os_window(OSWindow *os_window, double now, unsigned int *activ
if (is_active_window) {
*active_window_id = w->id;
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);
} 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;
@ -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);
set_maximum_wait(bell_left);
}
w->cursor_visible_at_last_render = WD.screen->cursor_render_info.is_visible;
}
}
swap_window_buffers(os_window);
@ -640,7 +642,7 @@ render(double now) {
for (size_t i = 0; i < global_state.num_os_windows; i++) {
OSWindow *w = global_state.os_windows + i;
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);
if (w->viewport_size_dirty) {
w->clear_count = 0;

View File

@ -271,6 +271,7 @@ def url_style(x):
'rectangle_select_modifiers': to_modifiers,
'repaint_delay': positive_int,
'input_delay': positive_int,
'sync_to_monitor': to_bool,
'window_border_width': positive_float,
'window_margin_width': positive_float,
'window_padding_width': positive_float,

View File

@ -346,7 +346,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args) {
glfwMakeContextCurrent(glfw_window);
if (x != -1 && y != -1) glfwSetWindowPos(glfw_window, x, y);
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) {
set_dpi_from_os_window(NULL);
gl_init();

View File

@ -127,7 +127,9 @@ initial_window_height 400
# Delay (in milliseconds) between screen updates. Decreasing it, increases
# 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
# Delay (in milliseconds) before input from the program running in the terminal
@ -137,6 +139,13 @@ repaint_delay 10
# screen updates will be drawn.
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
# seconds. Set to zero to disable.
visual_bell_duration 0.0

View File

@ -349,6 +349,7 @@ PYWRAP1(set_options) {
S(background, color_as_int);
S(repaint_delay, repaint_delay);
S(input_delay, repaint_delay);
S(sync_to_monitor, PyObject_IsTrue);
S(macos_option_as_alt, PyObject_IsTrue);
S(macos_hide_titlebar, PyObject_IsTrue);

View File

@ -30,6 +30,7 @@ typedef struct {
float background_opacity;
float inactive_text_alpha;
Edge tab_bar_edge;
bool sync_to_monitor;
} Options;
typedef struct {
@ -55,7 +56,7 @@ typedef struct {
typedef struct {
id_type id;
bool visible;
bool visible, cursor_visible_at_last_render;
PyObject *title;
ScreenRenderData render_data;
unsigned int mouse_cell_x, mouse_cell_y;
@ -108,10 +109,7 @@ typedef struct {
bool is_key_pressed[MAX_KEY_COUNT];
bool viewport_size_dirty;
double last_resize_event_at;
bool has_pending_resizes;
bool is_semi_transparent;
bool shown_once;
bool is_damaged;
bool has_pending_resizes, is_semi_transparent, shown_once, is_damaged;
uint32_t offscreen_texture_id;
unsigned int clear_count;
} OSWindow;