Two phases for redraw.

This commit is contained in:
Nicholas Marriott
2026-10-14 11:33:16 +01:00
parent d68e56f130
commit 464f404b85
2 changed files with 132 additions and 85 deletions

View File

@@ -72,6 +72,13 @@ enum redraw_span_type {
}; };
#define REDRAW_SPAN_TYPES 7 #define REDRAW_SPAN_TYPES 7
/* Draw phases. */
enum redraw_phase {
REDRAW_TEXT,
REDRAW_IMAGES
};
#define REDRAW_PHASE_COUNT 2
/* Border connections to adjacent cells. */ /* Border connections to adjacent cells. */
#define REDRAW_BORDER_L 0x1 #define REDRAW_BORDER_L 0x1
#define REDRAW_BORDER_R 0x2 #define REDRAW_BORDER_R 0x2
@@ -1503,31 +1510,35 @@ redraw_draw_menu_span(struct redraw_draw_ctx *dctx,
/* Draw a span. */ /* Draw a span. */
static void static void
redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span, redraw_draw_span(struct redraw_draw_ctx *dctx, struct redraw_span *span,
u_int y) u_int y, enum redraw_phase phase)
{ {
struct redraw_span_data *data = &span->data; struct redraw_span_data *data = &span->data;
enum redraw_span_type type = data->type; enum redraw_span_type type = data->type;
u_int width = span->width;
if (type == REDRAW_SPAN_STATUS && ~data->st.wp->flags & PANE_NEWSTATUS) if (type == REDRAW_SPAN_STATUS && ~data->st.wp->flags & PANE_NEWSTATUS)
return; return;
if (phase != REDRAW_TEXT && type != REDRAW_SPAN_PANE)
return;
switch (span->data.type) { switch (span->data.type) {
case REDRAW_SPAN_PANE: case REDRAW_SPAN_PANE:
redraw_draw_pane_span(dctx, span, span->x, y, span->width); if (phase == REDRAW_TEXT)
redraw_draw_pane_span(dctx, span, span->x, y, width);
break; break;
case REDRAW_SPAN_BORDER: case REDRAW_SPAN_BORDER:
case REDRAW_SPAN_EMPTY: case REDRAW_SPAN_EMPTY:
case REDRAW_SPAN_OUTSIDE: case REDRAW_SPAN_OUTSIDE:
redraw_draw_border_span(dctx, span, span->x, y, span->width); redraw_draw_border_span(dctx, span, span->x, y, width);
break; break;
case REDRAW_SPAN_STATUS: case REDRAW_SPAN_STATUS:
redraw_draw_status_span(dctx, span, span->x, y, span->width); redraw_draw_status_span(dctx, span, span->x, y, width);
break; break;
case REDRAW_SPAN_SCROLLBAR: case REDRAW_SPAN_SCROLLBAR:
redraw_draw_scrollbar_span(dctx, span, span->x, y, span->width); redraw_draw_scrollbar_span(dctx, span, span->x, y, width);
break; break;
case REDRAW_SPAN_MENU: case REDRAW_SPAN_MENU:
redraw_draw_menu_span(dctx, span, span->x, y, span->width); redraw_draw_menu_span(dctx, span, span->x, y, width);
break; break;
} }
} }
@@ -1541,6 +1552,7 @@ redraw_draw_pane_lines(struct redraw_draw_ctx *dctx, struct window_pane *wp,
struct redraw_line *line; struct redraw_line *line;
struct redraw_spans *spans; struct redraw_spans *spans;
struct redraw_span *span; struct redraw_span *span;
enum redraw_phase phase;
u_int cy; u_int cy;
int y, top, bottom; int y, top, bottom;
@@ -1553,6 +1565,8 @@ redraw_draw_pane_lines(struct redraw_draw_ctx *dctx, struct window_pane *wp,
if (bottom > (int)scene->sy) if (bottom > (int)scene->sy)
bottom = scene->sy; bottom = scene->sy;
/* Draw each phase. */
for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) {
for (y = top; y < bottom; y++) { for (y = top; y < bottom; y++) {
line = &scene->lines[y]; line = &scene->lines[y];
if (dctx->flags & REDRAW_STATUS_TOP) if (dctx->flags & REDRAW_STATUS_TOP)
@@ -1562,18 +1576,52 @@ redraw_draw_pane_lines(struct redraw_draw_ctx *dctx, struct window_pane *wp,
if (flags & REDRAW_PANE) { if (flags & REDRAW_PANE) {
spans = &line->spans[REDRAW_SPAN_PANE]; spans = &line->spans[REDRAW_SPAN_PANE];
TAILQ_FOREACH(span, spans, entry) { TAILQ_FOREACH(span, spans, entry) {
if (span->data.p.wp == wp) if (span->data.p.wp != wp)
redraw_draw_span(dctx, span, cy); continue;
redraw_draw_span(dctx, span, cy, phase);
} }
} }
if (flags & REDRAW_PANE_SCROLLBAR) { if (phase == REDRAW_TEXT &&
(flags & REDRAW_PANE_SCROLLBAR)) {
spans = &line->spans[REDRAW_SPAN_SCROLLBAR]; spans = &line->spans[REDRAW_SPAN_SCROLLBAR];
TAILQ_FOREACH(span, spans, entry) { TAILQ_FOREACH(span, spans, entry) {
if (span->data.sb.wp == wp) if (span->data.sb.wp != wp)
redraw_draw_span(dctx, span, cy); continue;
redraw_draw_span(dctx, span, cy, phase);
} }
} }
} }
}
}
/* Return whether to draw a span type in this phase for these flags. */
static int
redraw_should_draw(enum redraw_span_type type, int flags,
enum redraw_phase phase)
{
if (phase != REDRAW_TEXT && type != REDRAW_SPAN_PANE)
return (0);
if (REDRAW_IS_ALL(flags))
return (1);
switch (type) {
case REDRAW_SPAN_PANE:
return (flags & REDRAW_PANE);
case REDRAW_SPAN_OUTSIDE:
return (flags & REDRAW_OUTSIDE);
case REDRAW_SPAN_EMPTY:
return (flags & REDRAW_EMPTY);
case REDRAW_SPAN_BORDER:
return (flags & REDRAW_PANE_BORDER);
case REDRAW_SPAN_STATUS:
return (flags & REDRAW_PANE_STATUS);
case REDRAW_SPAN_SCROLLBAR:
return (flags & REDRAW_PANE_SCROLLBAR);
case REDRAW_SPAN_MENU:
return (flags & REDRAW_MENU);
default:
return (0);
}
} }
/* Draw lines. */ /* Draw lines. */
@@ -1584,8 +1632,11 @@ redraw_draw_lines(struct redraw_draw_ctx *dctx, int flags)
struct redraw_line *line; struct redraw_line *line;
struct redraw_spans *spans; struct redraw_spans *spans;
struct redraw_span *span; struct redraw_span *span;
enum redraw_phase phase;
u_int y, cy, type; u_int y, cy, type;
/* Draw each phase. */
for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) {
for (y = 0; y < scene->sy; y++) { for (y = 0; y < scene->sy; y++) {
line = &scene->lines[y]; line = &scene->lines[y];
if (dctx->flags & REDRAW_STATUS_TOP) if (dctx->flags & REDRAW_STATUS_TOP)
@@ -1593,43 +1644,12 @@ redraw_draw_lines(struct redraw_draw_ctx *dctx, int flags)
else else
cy = y; cy = y;
for (type = 0; type < REDRAW_SPAN_TYPES; type++) { for (type = 0; type < REDRAW_SPAN_TYPES; type++) {
if (!REDRAW_IS_ALL(flags)) { if (!redraw_should_draw(type, flags, phase))
switch (type) {
case REDRAW_SPAN_PANE:
if (~flags & REDRAW_PANE)
continue; continue;
break;
case REDRAW_SPAN_OUTSIDE:
if (~flags & REDRAW_OUTSIDE)
continue;
break;
case REDRAW_SPAN_EMPTY:
if (~flags & REDRAW_EMPTY)
continue;
break;
case REDRAW_SPAN_BORDER:
if (~flags & REDRAW_PANE_BORDER)
continue;
break;
case REDRAW_SPAN_STATUS:
if (~flags & REDRAW_PANE_STATUS)
continue;
break;
case REDRAW_SPAN_SCROLLBAR:
if (~flags & REDRAW_PANE_SCROLLBAR)
continue;
break;
case REDRAW_SPAN_MENU:
if (~flags & REDRAW_MENU)
continue;
break;
default:
continue;
}
}
spans = &line->spans[type]; spans = &line->spans[type];
TAILQ_FOREACH(span, spans, entry) TAILQ_FOREACH(span, spans, entry)
redraw_draw_span(dctx, span, cy); redraw_draw_span(dctx, span, cy, phase);
}
} }
} }
} }
@@ -1650,7 +1670,7 @@ redraw_draw_menu_lines(struct redraw_draw_ctx *dctx)
else else
cy = y; cy = y;
TAILQ_FOREACH(span, &line->spans[REDRAW_SPAN_MENU], entry) TAILQ_FOREACH(span, &line->spans[REDRAW_SPAN_MENU], entry)
redraw_draw_span(dctx, span, cy); redraw_draw_span(dctx, span, cy, REDRAW_TEXT);
} }
} }
@@ -2052,6 +2072,7 @@ redraw_draw_damage_rectangle(struct redraw_draw_ctx *dctx, u_int x, u_int y,
struct redraw_line *line; struct redraw_line *line;
struct redraw_spans *spans; struct redraw_spans *spans;
struct redraw_span *span; struct redraw_span *span;
enum redraw_phase phase;
u_int cy, yy, type; u_int cy, yy, type;
if (x >= scene->sx || y >= scene->sy) if (x >= scene->sx || y >= scene->sy)
@@ -2063,6 +2084,8 @@ redraw_draw_damage_rectangle(struct redraw_draw_ctx *dctx, u_int x, u_int y,
if (sx == 0 || sy == 0) if (sx == 0 || sy == 0)
return; return;
/* Draw each phase in the damaged spans. */
for (phase = 0; phase < REDRAW_PHASE_COUNT; phase++) {
for (yy = y; yy < y + sy; yy++) { for (yy = y; yy < y + sy; yy++) {
line = &scene->lines[yy]; line = &scene->lines[yy];
if (dctx->flags & REDRAW_STATUS_TOP) if (dctx->flags & REDRAW_STATUS_TOP)
@@ -2070,24 +2093,48 @@ redraw_draw_damage_rectangle(struct redraw_draw_ctx *dctx, u_int x, u_int y,
else else
cy = yy; cy = yy;
for (type = 0; type < REDRAW_SPAN_TYPES; type++) { for (type = 0; type < REDRAW_SPAN_TYPES; type++) {
if (phase != REDRAW_TEXT &&
type != REDRAW_SPAN_PANE)
continue;
if (type == REDRAW_SPAN_STATUS)
continue;
spans = &line->spans[type]; spans = &line->spans[type];
TAILQ_FOREACH(span, spans, entry) { TAILQ_FOREACH(span, spans, entry) {
if (span->x >= x + sx) if (span->x >= x + sx)
continue; continue;
if (span->x + span->width <= x) if (span->x + span->width <= x)
continue; continue;
if (type == REDRAW_SPAN_STATUS) { redraw_draw_span(dctx, span, cy, phase);
redraw_damage_refresh_status(dctx,
span->data.st.wp);
}
redraw_draw_span(dctx, span, cy);
if (type == REDRAW_SPAN_PANE) {
redraw_damage_draw_pane_prompt(dctx,
span, cy);
} }
} }
} }
} }
/* Draw prompts and pane status lines last. */
for (yy = y; yy < y + sy; yy++) {
line = &scene->lines[yy];
if (dctx->flags & REDRAW_STATUS_TOP)
cy = dctx->status_lines + yy;
else
cy = yy;
spans = &line->spans[REDRAW_SPAN_PANE];
TAILQ_FOREACH(span, spans, entry) {
if (span->x >= x + sx)
continue;
if (span->x + span->width <= x)
continue;
redraw_damage_draw_pane_prompt(dctx, span, cy);
}
spans = &line->spans[REDRAW_SPAN_STATUS];
TAILQ_FOREACH(span, spans, entry) {
if (span->x >= x + sx)
continue;
if (span->x + span->width <= x)
continue;
redraw_damage_refresh_status(dctx, span->data.st.wp);
redraw_draw_span(dctx, span, cy, REDRAW_TEXT);
}
}
} }
/* Draw pending window damage on this client. */ /* Draw pending window damage on this client. */