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
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);
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.col < term->sixel.image.width);
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];
int max_non_empty_row = 0;
int row = term->sixel.pos.row;
for (int i = 0; i < 6; i++, sixel >>= 1, data += width) {
if (sixel & 1) {
*data = color;
@ -1016,13 +1007,32 @@ sixel_add(struct terminal *term, uint32_t color, uint8_t sixel)
}
xassert(sixel == 0);
term->sixel.pos.col++;
term->sixel.max_non_empty_row_no = max(
term->sixel.max_non_empty_row_no,
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
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 'w': case 'x': case 'y': case 'z': case '{': case '|': case '}':
case '~':
sixel_add(term, term->sixel.palette[term->sixel.color_idx], c - 63);
sixel_add_many(term, c - 63, 1);
break;
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 '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 '~': {
//LOG_DBG("repeating '%c' %u times", c, 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);
case '~':
sixel_add_many(term, c - 63, term->sixel.param);
term->sixel.state = SIXEL_DECSIXEL;
break;
}
}
}
static void