mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	Merge pull request #22172 from bfredl/cells
perf(ui): mitigate redraw latency regression from TUI refactor
This commit is contained in:
		| @@ -4765,7 +4765,7 @@ A jump table for the options with a short description can be found at |Q_op|. | |||||||
| 	Flags to change the way redrawing works, for debugging purposes. | 	Flags to change the way redrawing works, for debugging purposes. | ||||||
| 	Most useful with 'writedelay' set to some reasonable value. | 	Most useful with 'writedelay' set to some reasonable value. | ||||||
| 	Supports the following flags: | 	Supports the following flags: | ||||||
| 	    compositor	Indicate what redraws come from the compositor | 	    compositor	Indicate each redraw event handled by the compositor | ||||||
| 			by briefly flashing the redrawn regions in colors | 			by briefly flashing the redrawn regions in colors | ||||||
| 			indicating the redraw type. These are the highlight | 			indicating the redraw type. These are the highlight | ||||||
| 			groups used (and their default colors): | 			groups used (and their default colors): | ||||||
| @@ -4777,6 +4777,11 @@ A jump table for the options with a short description can be found at |Q_op|. | |||||||
| 		RedrawDebugRecompose guibg=Red    redraw generated by the | 		RedrawDebugRecompose guibg=Red    redraw generated by the | ||||||
| 						  compositor itself, due to a | 						  compositor itself, due to a | ||||||
| 						  grid being moved or deleted. | 						  grid being moved or deleted. | ||||||
|  | 	    line	introduce a delay after each line drawn on the screen. | ||||||
|  | 			When using the TUI or another single-grid UI, "compositor" | ||||||
|  | 			gives more information and should be preferred (every | ||||||
|  | 			line is processed as a separate event by the compositor) | ||||||
|  | 	    flush	introduce a delay after each "flush" event. | ||||||
| 	    nothrottle	Turn off throttling of the message grid. This is an | 	    nothrottle	Turn off throttling of the message grid. This is an | ||||||
| 			optimization that joins many small scrolls to one | 			optimization that joins many small scrolls to one | ||||||
| 			larger scroll when drawing the message area (with | 			larger scroll when drawing the message area (with | ||||||
| @@ -7372,8 +7377,7 @@ A jump table for the options with a short description can be found at |Q_op|. | |||||||
| 						*'writedelay'* *'wd'* | 						*'writedelay'* *'wd'* | ||||||
| 'writedelay' 'wd'	number	(default 0) | 'writedelay' 'wd'	number	(default 0) | ||||||
| 			global | 			global | ||||||
| 	The number of milliseconds to wait for each character sent to the | 	Only takes effect toghether with 'redrawdebug'. | ||||||
| 	screen.  When positive, characters are sent to the UI one by one. | 	The number of milliseconds to wait after each line or each flush | ||||||
| 	See 'redrawdebug' for more options.  For debugging purposes. |  | ||||||
|  |  | ||||||
|  vim:tw=78:ts=8:noet:ft=help:norl: |  vim:tw=78:ts=8:noet:ft=help:norl: | ||||||
|   | |||||||
| @@ -202,6 +202,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona | |||||||
|   data->flushed_events = false; |   data->flushed_events = false; | ||||||
|   data->ncalls_pos = NULL; |   data->ncalls_pos = NULL; | ||||||
|   data->ncalls = 0; |   data->ncalls = 0; | ||||||
|  |   data->ncells_pending = 0; | ||||||
|   data->buf_wptr = data->buf; |   data->buf_wptr = data->buf; | ||||||
|   data->temp_buf = NULL; |   data->temp_buf = NULL; | ||||||
|   data->wildmenu_active = false; |   data->wildmenu_active = false; | ||||||
| @@ -854,18 +855,25 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int | |||||||
|             mpack_uint(buf, repeat); |             mpack_uint(buf, repeat); | ||||||
|           } |           } | ||||||
|         } |         } | ||||||
|  |         data->ncells_pending += MIN(repeat, 2); | ||||||
|         last_hl = attrs[i]; |         last_hl = attrs[i]; | ||||||
|         repeat = 0; |         repeat = 0; | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     if (endcol < clearcol) { |     if (endcol < clearcol) { | ||||||
|       nelem++; |       nelem++; | ||||||
|  |       data->ncells_pending += 1; | ||||||
|       mpack_array(buf, 3); |       mpack_array(buf, 3); | ||||||
|       mpack_str(buf, " "); |       mpack_str(buf, " "); | ||||||
|       mpack_uint(buf, (uint32_t)clearattr); |       mpack_uint(buf, (uint32_t)clearattr); | ||||||
|       mpack_uint(buf, (uint32_t)(clearcol - endcol)); |       mpack_uint(buf, (uint32_t)(clearcol - endcol)); | ||||||
|     } |     } | ||||||
|     mpack_w2(&lenpos, nelem); |     mpack_w2(&lenpos, nelem); | ||||||
|  |  | ||||||
|  |     if (data->ncells_pending > 500) { | ||||||
|  |       // pass of cells to UI to let it start processing them | ||||||
|  |       remote_ui_flush_buf(ui); | ||||||
|  |     } | ||||||
|   } else { |   } else { | ||||||
|     for (int i = 0; i < endcol - startcol; i++) { |     for (int i = 0; i < endcol - startcol; i++) { | ||||||
|       remote_ui_cursor_goto(ui, row, startcol + i); |       remote_ui_cursor_goto(ui, row, startcol + i); | ||||||
| @@ -917,6 +925,8 @@ void remote_ui_flush_buf(UI *ui) | |||||||
|   // we have sent events to the client, but possibly not yet the final "flush" |   // we have sent events to the client, but possibly not yet the final "flush" | ||||||
|   // event. |   // event. | ||||||
|   data->flushed_events = true; |   data->flushed_events = true; | ||||||
|  |  | ||||||
|  |   data->ncells_pending = 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| /// An intentional flush (vsync) when Nvim is finished redrawing the screen | /// An intentional flush (vsync) when Nvim is finished redrawing the screen | ||||||
|   | |||||||
| @@ -630,6 +630,8 @@ EXTERN unsigned rdb_flags; | |||||||
| #define RDB_NOTHROTTLE         0x002 | #define RDB_NOTHROTTLE         0x002 | ||||||
| #define RDB_INVALID            0x004 | #define RDB_INVALID            0x004 | ||||||
| #define RDB_NODELTA            0x008 | #define RDB_NODELTA            0x008 | ||||||
|  | #define RDB_LINE               0x010 | ||||||
|  | #define RDB_FLUSH              0x020 | ||||||
|  |  | ||||||
| EXTERN long p_rdt;            // 'redrawtime' | EXTERN long p_rdt;            // 'redrawtime' | ||||||
| EXTERN long p_re;             // 'regexpengine' | EXTERN long p_re;             // 'regexpengine' | ||||||
|   | |||||||
| @@ -125,7 +125,8 @@ static char *(p_spo_values[]) = { "camel", "noplainbuffer", NULL }; | |||||||
| static char *(p_icm_values[]) = { "nosplit", "split", NULL }; | static char *(p_icm_values[]) = { "nosplit", "split", NULL }; | ||||||
| static char *(p_jop_values[]) = { "stack", "view", NULL }; | static char *(p_jop_values[]) = { "stack", "view", NULL }; | ||||||
| static char *(p_tpf_values[]) = { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NULL }; | static char *(p_tpf_values[]) = { "BS", "HT", "FF", "ESC", "DEL", "C0", "C1", NULL }; | ||||||
| static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", NULL }; | static char *(p_rdb_values[]) = { "compositor", "nothrottle", "invalid", "nodelta", "line", | ||||||
|  |                                   "flush", NULL }; | ||||||
| static char *(p_sloc_values[]) = { "last", "statusline", "tabline", NULL }; | static char *(p_sloc_values[]) = { "last", "statusline", "tabline", NULL }; | ||||||
|  |  | ||||||
| /// All possible flags for 'shm'. | /// All possible flags for 'shm'. | ||||||
|   | |||||||
| @@ -419,7 +419,7 @@ void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol, | |||||||
|                    (const sattr_T *)grid->attrs + off); |                    (const sattr_T *)grid->attrs + off); | ||||||
|  |  | ||||||
|   // 'writedelay': flush & delay each time. |   // 'writedelay': flush & delay each time. | ||||||
|   if (p_wd && !(rdb_flags & RDB_COMPOSITOR)) { |   if (p_wd && (rdb_flags & RDB_LINE)) { | ||||||
|     // If 'writedelay' is active, set the cursor to indicate what was drawn. |     // If 'writedelay' is active, set the cursor to indicate what was drawn. | ||||||
|     ui_call_grid_cursor_goto(grid->handle, row, |     ui_call_grid_cursor_goto(grid->handle, row, | ||||||
|                              MIN(clearcol, (int)grid->cols - 1)); |                              MIN(clearcol, (int)grid->cols - 1)); | ||||||
| @@ -510,6 +510,10 @@ void ui_flush(void) | |||||||
|     pending_has_mouse = has_mouse; |     pending_has_mouse = has_mouse; | ||||||
|   } |   } | ||||||
|   ui_call_flush(); |   ui_call_flush(); | ||||||
|  |  | ||||||
|  |   if (p_wd && (rdb_flags & RDB_FLUSH)) { | ||||||
|  |     os_microdelay((uint64_t)labs(p_wd) * 1000U, true); | ||||||
|  |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Check if 'mouse' is active for the current mode | /// Check if 'mouse' is active for the current mode | ||||||
|   | |||||||
| @@ -79,6 +79,8 @@ typedef struct { | |||||||
|   uint32_t ncalls;  ///< number of calls made to the current event (plus one for the name!) |   uint32_t ncalls;  ///< number of calls made to the current event (plus one for the name!) | ||||||
|   bool flushed_events;  ///< events where sent to client without "flush" event |   bool flushed_events;  ///< events where sent to client without "flush" event | ||||||
|  |  | ||||||
|  |   size_t ncells_pending;  ///< total number of cells since last buffer flush | ||||||
|  |  | ||||||
|   int hl_id;  // Current highlight for legacy put event. |   int hl_id;  // Current highlight for legacy put event. | ||||||
|   Integer cursor_row, cursor_col;  // Intended visible cursor position. |   Integer cursor_row, cursor_col;  // Intended visible cursor position. | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 bfredl
					bfredl