sixel: add: add sixel_add_many(), improving performance of DECGRI

DECGRI, i.e. repeat sixel character, only need to do image resizing,
and updating the current ‘column’ value *once*.

By adding sixel_add_many(), and doing the size/resize checking there,
the performance of sixel_add() is made much simpler.

This boosts performance quite noticeably when the application is
emitting many and/or long repeat sequences.
This commit is contained in:
Daniel Eklöf 2021-03-07 16:30:48 +01:00
parent 6e963dbf68
commit 6d208fa5e0
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F

51
sixel.c
View file

@ -988,26 +988,17 @@ resize(struct terminal *term, int new_width, int new_height)
} }
static void static void
sixel_add(struct terminal *term, uint32_t color, uint8_t sixel) sixel_add(struct terminal *term, int col, int width, uint32_t color, uint8_t sixel)
{ {
//LOG_DBG("adding sixel %02hhx using color 0x%06x", sixel, color); xassert(term->sixel.pos.col < term->sixel.image.width);
int width = term->sixel.image.width;
if (unlikely(term->sixel.pos.col >= width)) {
width = term->sixel.pos.col + 1;
if (unlikely(!resize_horizontally(term, width)))
return;
}
/* Height adjustment done while processing - */
xassert(term->sixel.pos.row < term->sixel.image.height); xassert(term->sixel.pos.row < term->sixel.image.height);
size_t ofs = term->sixel.row_byte_ofs + term->sixel.pos.col; size_t ofs = term->sixel.row_byte_ofs + col;
uint32_t *data = &term->sixel.image.data[ofs]; uint32_t *data = &term->sixel.image.data[ofs];
int max_non_empty_row = 0; int max_non_empty_row = 0;
int row = term->sixel.pos.row; int row = term->sixel.pos.row;
for (int i = 0; i < 6; i++, sixel >>= 1, data += width) { for (int i = 0; i < 6; i++, sixel >>= 1, data += width) {
if (sixel & 1) { if (sixel & 1) {
*data = color; *data = color;
@ -1016,13 +1007,32 @@ sixel_add(struct terminal *term, uint32_t color, uint8_t sixel)
} }
xassert(sixel == 0); xassert(sixel == 0);
term->sixel.pos.col++;
term->sixel.max_non_empty_row_no = max( term->sixel.max_non_empty_row_no = max(
term->sixel.max_non_empty_row_no, term->sixel.max_non_empty_row_no,
max_non_empty_row); max_non_empty_row);
} }
static void
sixel_add_many(struct terminal *term, uint8_t c, unsigned count)
{
uint32_t color = term->sixel.palette[term->sixel.color_idx];
int col = term->sixel.pos.col;
int width = term->sixel.image.width;
if (unlikely(col + count - 1 >= width)) {
width = col + count;
if (unlikely(!resize_horizontally(term, width)))
return;
}
for (unsigned i = 0; i < count; i++, col++)
sixel_add(term, col, width, color, c);
term->sixel.pos.col = col;
}
static void static void
decsixel(struct terminal *term, uint8_t c) decsixel(struct terminal *term, uint8_t c)
{ {
@ -1079,7 +1089,7 @@ decsixel(struct terminal *term, uint8_t c)
case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v':
case 'w': case 'x': case 'y': case 'z': case '{': case '|': case '}': case 'w': case 'x': case 'y': case 'z': case '{': case '|': case '}':
case '~': case '~':
sixel_add(term, term->sixel.palette[term->sixel.color_idx], c - 63); sixel_add_many(term, c - 63, 1);
break; break;
case ' ': case ' ':
@ -1157,18 +1167,11 @@ decgri(struct terminal *term, uint8_t c)
case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v':
case 'w': case 'x': case 'y': case 'z': case '{': case '|': case '}': case 'w': case 'x': case 'y': case 'z': case '{': case '|': case '}':
case '~': { case '~':
//LOG_DBG("repeating '%c' %u times", c, term->sixel.param); sixel_add_many(term, c - 63, term->sixel.param);
unsigned count = term->sixel.param;
uint32_t color = term->sixel.palette[term->sixel.color_idx];
for (unsigned i = 0; i < count; i++)
sixel_add(term, color, c - 63);
term->sixel.state = SIXEL_DECSIXEL; term->sixel.state = SIXEL_DECSIXEL;
break; break;
} }
}
} }
static void static void