aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-02-12 13:02:27 +0800
committerGitHub <noreply@github.com>2024-02-12 13:02:27 +0800
commit929e1b7f1c35679424989f5ebfc78f095bb434d9 (patch)
tree9926fa873746da91cb2564c4d2606ff11829817e /src
parent950a0ac61c70362f168338b815675ac60b1d72dc (diff)
downloadrneovim-929e1b7f1c35679424989f5ebfc78f095bb434d9.tar.gz
rneovim-929e1b7f1c35679424989f5ebfc78f095bb434d9.tar.bz2
rneovim-929e1b7f1c35679424989f5ebfc78f095bb434d9.zip
perf(extmarks): avoid unnecessary invalidations for virt_text (#27435)
Invalidation of most w_valid flags isn't needed when adding or removing virtual text below cursor.
Diffstat (limited to 'src')
-rw-r--r--src/nvim/change.c124
-rw-r--r--src/nvim/decoration.c14
-rw-r--r--src/nvim/extmark.c11
-rw-r--r--src/nvim/help.c2
-rw-r--r--src/nvim/move.c13
5 files changed, 86 insertions, 78 deletions
diff --git a/src/nvim/change.c b/src/nvim/change.c
index e01921a826..2db3d007d7 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -163,6 +163,71 @@ void changed_internal(buf_T *buf)
need_maketitle = true; // set window title later
}
+/// Invalidate a window's w_valid flags and w_lines[] entries after changing lines.
+static void changed_lines_invalidate_win(win_T *wp, linenr_T lnum, colnr_T col, linenr_T lnume,
+ linenr_T xtra)
+{
+ // If the changed line is in a range of previously folded lines,
+ // compare with the first line in that range.
+ if (wp->w_cursor.lnum <= lnum) {
+ int i = find_wl_entry(wp, lnum);
+ if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum) {
+ changed_line_abv_curs_win(wp);
+ }
+ }
+
+ if (wp->w_cursor.lnum > lnum) {
+ changed_line_abv_curs_win(wp);
+ } else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col) {
+ changed_cline_bef_curs(wp);
+ }
+ if (wp->w_botline >= lnum) {
+ // Assume that botline doesn't change (inserted lines make
+ // other lines scroll down below botline).
+ approximate_botline_win(wp);
+ }
+
+ // Check if any w_lines[] entries have become invalid.
+ // For entries below the change: Correct the lnums for inserted/deleted lines.
+ // Makes it possible to stop displaying after the change.
+ for (int i = 0; i < wp->w_lines_valid; i++) {
+ if (wp->w_lines[i].wl_valid) {
+ if (wp->w_lines[i].wl_lnum >= lnum) {
+ // Do not change wl_lnum at index zero, it is used to compare with w_topline.
+ // Invalidate it instead.
+ // If lines haven been inserted/deleted and the buffer has virt_lines,
+ // invalidate the line after the changed lines as some virt_lines may
+ // now be drawn above a different line.
+ if (i == 0 || wp->w_lines[i].wl_lnum < lnume
+ || (xtra != 0 && wp->w_lines[i].wl_lnum == lnume
+ && buf_meta_total(wp->w_buffer, kMTMetaLines) > 0)) {
+ // line included in change
+ wp->w_lines[i].wl_valid = false;
+ } else if (xtra != 0) {
+ // line below change
+ wp->w_lines[i].wl_lnum += xtra;
+ wp->w_lines[i].wl_lastlnum += xtra;
+ }
+ } else if (wp->w_lines[i].wl_lastlnum >= lnum) {
+ // change somewhere inside this range of folded lines,
+ // may need to be redrawn
+ wp->w_lines[i].wl_valid = false;
+ }
+ }
+ }
+}
+
+/// Line changed_lines_invalidate_win(), but for all windows displaying a buffer.
+void changed_lines_invalidate_buf(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnume,
+ linenr_T xtra)
+{
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_buffer == buf) {
+ changed_lines_invalidate_win(wp, lnum, col, lnume, xtra);
+ }
+ }
+}
+
/// Common code for when a change was made.
/// See changed_lines() for the arguments.
/// Careful: may trigger autocommands that reload the buffer.
@@ -296,55 +361,7 @@ static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnum
wp->w_cline_folded = folded;
}
- // If the changed line is in a range of previously folded lines,
- // compare with the first line in that range.
- if (wp->w_cursor.lnum <= lnum) {
- int i = find_wl_entry(wp, lnum);
- if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum) {
- changed_line_abv_curs_win(wp);
- }
- }
-
- if (wp->w_cursor.lnum > lnum) {
- changed_line_abv_curs_win(wp);
- } else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col) {
- changed_cline_bef_curs(wp);
- }
- if (wp->w_botline >= lnum) {
- // Assume that botline doesn't change (inserted lines make
- // other lines scroll down below botline).
- approximate_botline_win(wp);
- }
-
- // Check if any w_lines[] entries have become invalid.
- // For entries below the change: Correct the lnums for
- // inserted/deleted lines. Makes it possible to stop displaying
- // after the change.
- for (int i = 0; i < wp->w_lines_valid; i++) {
- if (wp->w_lines[i].wl_valid) {
- if (wp->w_lines[i].wl_lnum >= lnum) {
- // Do not change wl_lnum at index zero, it is used to
- // compare with w_topline. Invalidate it instead.
- // If the buffer has virt_lines, invalidate the line
- // after the changed lines as the virt_lines for a
- // changed line may become invalid.
- if (i == 0 || wp->w_lines[i].wl_lnum < lnume
- || (wp->w_lines[i].wl_lnum == lnume
- && buf_meta_total(wp->w_buffer, kMTMetaLines) > 0)) {
- // line included in change
- wp->w_lines[i].wl_valid = false;
- } else if (xtra != 0) {
- // line below change
- wp->w_lines[i].wl_lnum += xtra;
- wp->w_lines[i].wl_lastlnum += xtra;
- }
- } else if (wp->w_lines[i].wl_lastlnum >= lnum) {
- // change somewhere inside this range of folded lines,
- // may need to be redrawn
- wp->w_lines[i].wl_valid = false;
- }
- }
- }
+ changed_lines_invalidate_win(wp, lnum, col, lnume, xtra);
// Take care of side effects for setting w_topline when folds have
// changed. Esp. when the buffer was changed in another window.
@@ -488,13 +505,13 @@ void deleted_lines_mark(linenr_T lnum, int count)
}
/// Marks the area to be redrawn after a change.
-/// Consider also calling changed_line_display_buf().
+/// Consider also calling changed_lines_invalidate_buf().
///
/// @param buf the buffer where lines were changed
/// @param lnum first line with change
/// @param lnume line below last changed line
/// @param xtra number of extra lines (negative when deleting)
-void buf_redraw_changed_lines_later(buf_T *buf, linenr_T lnum, linenr_T lnume, linenr_T xtra)
+void changed_lines_redraw_buf(buf_T *buf, linenr_T lnum, linenr_T lnume, linenr_T xtra)
{
if (buf->b_mod_set) {
// find the maximum area that must be redisplayed
@@ -542,7 +559,7 @@ void buf_redraw_changed_lines_later(buf_T *buf, linenr_T lnum, linenr_T lnume, l
void changed_lines(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T xtra,
bool do_buf_event)
{
- buf_redraw_changed_lines_later(buf, lnum, lnume, xtra);
+ changed_lines_redraw_buf(buf, lnum, lnume, xtra);
if (xtra == 0 && curwin->w_p_diff && curwin->w_buffer == buf && !diff_internal()) {
// When the number of lines doesn't change then mark_adjust() isn't
@@ -555,8 +572,7 @@ void changed_lines(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnume, linen
redraw_later(wp, UPD_VALID);
wlnum = diff_lnum_win(lnum, wp);
if (wlnum > 0) {
- buf_redraw_changed_lines_later(wp->w_buffer, wlnum,
- lnume - lnum + wlnum, 0);
+ changed_lines_redraw_buf(wp->w_buffer, wlnum, lnume - lnum + wlnum, 0);
}
}
}
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 95502e176c..e4828bcc31 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -10,6 +10,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
+#include "nvim/change.h"
#include "nvim/decoration.h"
#include "nvim/drawscreen.h"
#include "nvim/extmark.h"
@@ -91,15 +92,18 @@ void bufhl_add_hl_pos_offset(buf_T *buf, int src_id, int hl_id, lpos_T pos_start
}
}
-void decor_redraw(buf_T *buf, int row1, int row2, DecorInline decor)
+void decor_redraw(buf_T *buf, int row1, int row2, int col1, DecorInline decor)
{
if (decor.ext) {
DecorVirtText *vt = decor.data.ext.vt;
while (vt) {
bool below = (vt->flags & kVTIsLines) && !(vt->flags & kVTLinesAbove);
- redraw_buf_line_later(buf, row1 + 1 + below, true);
+ linenr_T vt_lnum = row1 + 1 + below;
+ redraw_buf_line_later(buf, vt_lnum, true);
if (vt->flags & kVTIsLines || vt->pos == kVPosInline) {
- changed_line_display_buf(buf);
+ // changed_lines_redraw_buf(buf, vt_lnum, vt_lnum + 1, 0);
+ colnr_T vt_col = vt->flags & kVTIsLines ? 0 : col1;
+ changed_lines_invalidate_buf(buf, vt_lnum, vt_col, vt_lnum + 1, 0);
}
vt = vt->next;
}
@@ -190,9 +194,9 @@ void buf_put_decor_sh(buf_T *buf, DecorSignHighlight *sh, int row1, int row2)
}
}
-void buf_decor_remove(buf_T *buf, int row1, int row2, DecorInline decor, bool free)
+void buf_decor_remove(buf_T *buf, int row1, int row2, int col1, DecorInline decor, bool free)
{
- decor_redraw(buf, row1, row2, decor);
+ decor_redraw(buf, row1, row2, col1, decor);
if (decor.ext) {
uint32_t idx = decor.data.ext.sh_idx;
while (idx != DECOR_ID_INVALID) {
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 93a2b9c16a..0f9e7749f1 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -75,7 +75,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
// not paired: we can revise in place
if (!invalid && mt_decor_any(old_mark)) {
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_DECOR_SIGNTEXT;
- buf_decor_remove(buf, row, row, mt_decor(old_mark), true);
+ buf_decor_remove(buf, row, row, col, mt_decor(old_mark), true);
}
mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_EXTERNAL_MASK;
mt_itr_rawkey(itr).flags |= flags;
@@ -84,7 +84,8 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
}
marktree_del_itr(buf->b_marktree, itr, false);
if (!invalid) {
- buf_decor_remove(buf, old_mark.pos.row, old_mark.pos.row, mt_decor(old_mark), true);
+ buf_decor_remove(buf, old_mark.pos.row, old_mark.pos.row, old_mark.pos.col,
+ mt_decor(old_mark), true);
}
}
} else {
@@ -99,7 +100,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
revised:
if (decor_flags || decor.ext) {
buf_put_decor(buf, decor, row, end_row > -1 ? end_row : row);
- decor_redraw(buf, row, end_row > -1 ? end_row : row, decor);
+ decor_redraw(buf, row, end_row > -1 ? end_row : row, col, decor);
}
if (idp) {
@@ -170,7 +171,7 @@ void extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
if (mt_invalid(key)) {
decor_free(mt_decor(key));
} else {
- buf_decor_remove(buf, key.pos.row, key2.pos.row, mt_decor(key), true);
+ buf_decor_remove(buf, key.pos.row, key2.pos.row, key.pos.col, mt_decor(key), true);
}
}
@@ -369,7 +370,7 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln
} else {
invalidated = true;
mt_itr_rawkey(itr).flags |= MT_FLAG_INVALID;
- buf_decor_remove(buf, mark.pos.row, endpos.row, mt_decor(mark), false);
+ buf_decor_remove(buf, mark.pos.row, endpos.row, mark.pos.col, mt_decor(mark), false);
}
}
}
diff --git a/src/nvim/help.c b/src/nvim/help.c
index 879e2801a7..779772cedf 100644
--- a/src/nvim/help.c
+++ b/src/nvim/help.c
@@ -803,7 +803,7 @@ void get_local_additions(void)
linenr_T appended = lnum - lnum_start;
if (appended) {
mark_adjust(lnum_start + 1, (linenr_T)MAXLNUM, appended, 0, kExtmarkUndo);
- buf_redraw_changed_lines_later(curbuf, lnum_start + 1, lnum_start + 1, appended);
+ changed_lines_redraw_buf(curbuf, lnum_start + 1, lnum_start + 1, appended);
}
break;
}
diff --git a/src/nvim/move.c b/src/nvim/move.c
index 1cf6e52ec8..551aa1bd4d 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -595,19 +595,6 @@ void changed_line_abv_curs_win(win_T *wp)
|VALID_CHEIGHT|VALID_TOPLINE);
}
-/// Display of line has changed for "buf", invalidate cursor position and
-/// w_botline.
-void changed_line_display_buf(buf_T *buf)
-{
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == buf) {
- wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL
- |VALID_CROW|VALID_CHEIGHT
- |VALID_TOPLINE|VALID_BOTLINE|VALID_BOTLINE_AP);
- }
- }
-}
-
// Make sure the value of curwin->w_botline is valid.
void validate_botline(win_T *wp)
{