mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
selection/render: sync cells' 'selected' bit before rendering
For performance reasons, we track whether a cell is selected or not using a bit in a cell's attributes. This makes it easy for the renderer to determine if the cells should be rendered as selected or not - it just have to look at the 'selected' bit instead of doing a complex range check against the current selection. This works nicely in most cases. But, if the cell is updated, the 'selected' bit is cleared. This results in the renderer rendering the cell normally, i.e. _not_ selected. Checking for this, and re-setting the 'selected' bit when the cell is updated (printed to) is way too expensive as it is in the hot path. Instead, sync the 'selected' bits just before rendering. This isn't so bad as it may sound; if there is no selection this is a no-op. Even if there is a selection, only those cells whose 'selected' bit have been cleared are dirtied (and thus re-rendered) - these cells would have been re-rendered anyway.
This commit is contained in:
parent
a1c95562fb
commit
1a8ccb0ffa
4 changed files with 31 additions and 0 deletions
|
|
@ -30,6 +30,7 @@
|
||||||
`shift` to start a selection. This selection is now finalized only
|
`shift` to start a selection. This selection is now finalized only
|
||||||
when the mouse button is released - not as soon as `shift` is
|
when the mouse button is released - not as soon as `shift` is
|
||||||
released.
|
released.
|
||||||
|
* Selected cells did not appear selected if modified.
|
||||||
|
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
|
||||||
19
render.c
19
render.c
|
|
@ -1354,6 +1354,25 @@ grid_render(struct terminal *term)
|
||||||
/* Reset clip region since scrolling may have instantiated a new pixman image */
|
/* Reset clip region since scrolling may have instantiated a new pixman image */
|
||||||
pixman_image_set_clip_region(buf->pix, &clip);
|
pixman_image_set_clip_region(buf->pix, &clip);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ensure selected cells have their 'selected' bit set. This is
|
||||||
|
* normally "automatically" true - the bit is set when the
|
||||||
|
* selection is made.
|
||||||
|
*
|
||||||
|
* However, if the cell is updated (printed to) while the
|
||||||
|
* selection is active, the 'selected' bit is cleared. Checking
|
||||||
|
* for this and re-setting the bit in term_print() is too
|
||||||
|
* expensive performance wise.
|
||||||
|
*
|
||||||
|
* Instead, we synchronize the selection bits here and now. This
|
||||||
|
* makes the performance impact linear to the number of selected
|
||||||
|
* cells rather than to the number of updated cells.
|
||||||
|
*
|
||||||
|
* (note that selection_dirty_cells() will not set the dirty flag
|
||||||
|
* on cells where the 'selected' bit is already set)
|
||||||
|
*/
|
||||||
|
selection_dirty_cells(term);
|
||||||
|
|
||||||
if (term->render.workers.count > 0) {
|
if (term->render.workers.count > 0) {
|
||||||
|
|
||||||
term->render.workers.buf = buf;
|
term->render.workers.buf = buf;
|
||||||
|
|
|
||||||
10
selection.c
10
selection.c
|
|
@ -403,6 +403,16 @@ selection_update(struct terminal *term, int col, int row)
|
||||||
selection_modify(term, term->selection.start, new_end);
|
selection_modify(term, term->selection.start, new_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
selection_dirty_cells(struct terminal *term)
|
||||||
|
{
|
||||||
|
if (term->selection.start.row == -1 || term->selection.end.row == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach_selected(
|
||||||
|
term, term->selection.start, term->selection.end, &mark_selected, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
selection_extend_normal(struct terminal *term, int col, int row, uint32_t serial)
|
selection_extend_normal(struct terminal *term, int col, int row, uint32_t serial)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ void selection_start(
|
||||||
struct terminal *term, int col, int row, enum selection_kind kind);
|
struct terminal *term, int col, int row, enum selection_kind kind);
|
||||||
void selection_update(struct terminal *term, int col, int row);
|
void selection_update(struct terminal *term, int col, int row);
|
||||||
void selection_finalize(struct terminal *term, uint32_t serial);
|
void selection_finalize(struct terminal *term, uint32_t serial);
|
||||||
|
void selection_dirty_cells(struct terminal *term);
|
||||||
void selection_cancel(struct terminal *term);
|
void selection_cancel(struct terminal *term);
|
||||||
void selection_extend(struct terminal *term, int col, int row, uint32_t serial);
|
void selection_extend(struct terminal *term, int col, int row, uint32_t serial);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue