render: special case worker-count == 0

Allow render worker count to be 0, in which case the main thread
renders the entire screen.
This commit is contained in:
Daniel Eklöf 2019-08-01 20:09:39 +02:00
parent bd734d5bed
commit 57564c2b59
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F

View file

@ -137,12 +137,12 @@ arm_blink_timer(struct terminal *term)
term->blink.active = true; term->blink.active = true;
} }
static void static int
render_cell(struct terminal *term, cairo_t *cr, render_cell(struct terminal *term, cairo_t *cr,
struct cell *cell, int col, int row, bool has_cursor) struct cell *cell, int col, int row, bool has_cursor)
{ {
if (cell->attrs.clean) if (cell->attrs.clean)
return; return 0;
cell->attrs.clean = 1; cell->attrs.clean = 1;
@ -211,7 +211,7 @@ render_cell(struct terminal *term, cairo_t *cr,
} }
if (cell->c[0] == '\0' || cell->attrs.conceal) if (cell->c[0] == '\0' || cell->attrs.conceal)
return; return cell_cols;
if (glyph != NULL) { if (glyph != NULL) {
cairo_save(cr); cairo_save(cr);
@ -244,6 +244,8 @@ render_cell(struct terminal *term, cairo_t *cr,
if (cell->attrs.strikethrough) if (cell->attrs.strikethrough)
draw_strikeout(term, cr, attrs_to_font(term, &cell->attrs), fg, x, y, cell_cols); draw_strikeout(term, cr, attrs_to_font(term, &cell->attrs), fg, x, y, cell_cols);
return cell_cols;
} }
static void static void
@ -461,38 +463,58 @@ grid_render(struct terminal *term)
tll_remove(term->grid->scroll_damage, it); tll_remove(term->grid->scroll_damage, it);
} }
term->render.workers.buf = buf; if (term->render.workers.count > 0) {
for (size_t i = 0; i < term->render.workers.count; i++)
sem_post(&term->render.workers.start);
assert(tll_length(term->render.workers.queue) == 0); term->render.workers.buf = buf;
for (size_t i = 0; i < term->render.workers.count; i++)
sem_post(&term->render.workers.start);
for (int r = 0; r < term->rows; r++) { assert(tll_length(term->render.workers.queue) == 0);
struct row *row = grid_row_in_view(term->grid, r);
if (!row->dirty) for (int r = 0; r < term->rows; r++) {
continue; struct row *row = grid_row_in_view(term->grid, r);
if (!row->dirty)
continue;
mtx_lock(&term->render.workers.lock);
tll_push_back(term->render.workers.queue, r);
cnd_signal(&term->render.workers.cond);
mtx_unlock(&term->render.workers.lock);
row->dirty = false;
all_clean = false;
wl_surface_damage_buffer(
term->wl.surface,
0, r * term->cell_height,
term->width, term->cell_height);
}
mtx_lock(&term->render.workers.lock); mtx_lock(&term->render.workers.lock);
tll_push_back(term->render.workers.queue, r); for (size_t i = 0; i < term->render.workers.count; i++)
cnd_signal(&term->render.workers.cond); tll_push_back(term->render.workers.queue, -1);
cnd_broadcast(&term->render.workers.cond);
mtx_unlock(&term->render.workers.lock); mtx_unlock(&term->render.workers.lock);
} else {
for (int r = 0; r < term->rows; r++) {
struct row *row = grid_row_in_view(term->grid, r);
row->dirty = false; if (!row->dirty)
all_clean = false; continue;
wl_surface_damage_buffer( render_row(term, cr, row, r);
term->wl.surface,
0, r * term->cell_height, row->dirty = false;
term->width, term->cell_height); all_clean = false;
wl_surface_damage_buffer(
term->wl.surface,
0, r * term->cell_height,
term->width, term->cell_height);
}
} }
mtx_lock(&term->render.workers.lock);
for (size_t i = 0; i < term->render.workers.count; i++)
tll_push_back(term->render.workers.queue, -1);
cnd_broadcast(&term->render.workers.cond);
mtx_unlock(&term->render.workers.lock);
if (term->blink.active) { if (term->blink.active) {
/* Check if there are still any visible blinking cells */ /* Check if there are still any visible blinking cells */
bool none_is_blinking = true; bool none_is_blinking = true;
@ -539,9 +561,16 @@ grid_render(struct terminal *term)
cursor_is_visible = true; cursor_is_visible = true;
} }
for (size_t i = 0; i < term->render.workers.count; i++) /*
sem_wait(&term->render.workers.done); * Wait for workers to finish before we render the cursor. This is
term->render.workers.buf = NULL; * because the cursor cell might be dirty, in which case a worker
* will render it (but without the cursor).
*/
if (term->render.workers.count > 0) {
for (size_t i = 0; i < term->render.workers.count; i++)
sem_wait(&term->render.workers.done);
term->render.workers.buf = NULL;
}
if (cursor_is_visible && !term->hide_cursor) { if (cursor_is_visible && !term->hide_cursor) {
/* Remember cursor coordinates so that we can erase it next /* Remember cursor coordinates so that we can erase it next
@ -559,14 +588,14 @@ grid_render(struct terminal *term)
cell->attrs.clean = 0; cell->attrs.clean = 0;
term->render.last_cursor.cell = cell; term->render.last_cursor.cell = cell;
render_cell( int cols_updated = render_cell(
term, cr, cell, term->cursor.col, view_aligned_row, true); term, cr, cell, term->cursor.col, view_aligned_row, true);
wl_surface_damage_buffer( wl_surface_damage_buffer(
term->wl.surface, term->wl.surface,
term->cursor.col * term->cell_width, term->cursor.col * term->cell_width,
view_aligned_row * term->cell_height, view_aligned_row * term->cell_height,
2 * term->cell_width, term->cell_height); cols_updated * term->cell_width, term->cell_height);
} }
if (all_clean) { if (all_clean) {
@ -652,7 +681,7 @@ render_resize(struct terminal *term, int width, int height)
term->width = width; term->width = width;
term->height = height; term->height = height;
const int scrollback_lines = 1000; const int scrollback_lines = term->render.scrollback_lines;
const int old_cols = term->cols; const int old_cols = term->cols;
const int old_rows = term->rows; const int old_rows = term->rows;