Split up the color field into fg/bg colors

Avoid a lot of unnecessary masking as well as unaligned read/writes
This commit is contained in:
Kovid Goyal 2017-05-15 08:32:52 +05:30
parent 800291c147
commit 69b187a743
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 64 additions and 63 deletions

View File

@ -17,8 +17,7 @@
#define MIN(x, y) (((x) > (y)) ? (y) : (x))
typedef Py_UCS4 char_type;
typedef uint64_t color_type;
typedef uint32_t decoration_type;
typedef uint32_t color_type;
typedef uint32_t combining_type;
typedef unsigned int index_type;
@ -31,7 +30,8 @@ typedef unsigned int index_type;
#define SGR_PROTOCOL 2
#define URXVT_PROTOCOL 3
#define CELL_SIZE (sizeof(char_type) + sizeof(color_type) + sizeof(decoration_type) + sizeof(combining_type))
#define CELL_FIELD_COUNT 5
#define CELL_SIZE (CELL_FIELD_COUNT * 4)
// The data cell size must be a multiple of 3
#define DATA_CELL_SIZE 2 * 3
@ -46,8 +46,6 @@ typedef unsigned int index_type;
#define REVERSE_SHIFT 6
#define STRIKE_SHIFT 7
#define COL_MASK 0xFFFFFFFF
#define COL_SHIFT 32
#define HAS_BG_MASK (0xFF << COL_SHIFT)
#define CC_MASK 0xFFFF
#define CC_SHIFT 16
#define UTF8_ACCEPT 0
@ -77,7 +75,8 @@ typedef unsigned int index_type;
#define COPY_CELL(src, s, dest, d) \
(dest)->chars[d] = (src)->chars[s]; \
(dest)->colors[d] = (src)->colors[s]; \
(dest)->fg_colors[d] = (src)->fg_colors[s]; \
(dest)->bg_colors[d] = (src)->bg_colors[s]; \
(dest)->decoration_fg[d] = (src)->decoration_fg[s]; \
(dest)->combining_chars[d] = (src)->combining_chars[s];
@ -85,18 +84,17 @@ typedef unsigned int index_type;
#define COPY_LINE(src, dest) \
memcpy((dest)->chars, (src)->chars, sizeof(char_type) * MIN((src)->xnum, (dest)->xnum)); \
memcpy((dest)->colors, (src)->colors, sizeof(color_type) * MIN((src)->xnum, (dest)->xnum)); \
memcpy((dest)->decoration_fg, (src)->decoration_fg, sizeof(decoration_type) * MIN((src)->xnum, (dest)->xnum)); \
memcpy((dest)->fg_colors, (src)->fg_colors, sizeof(color_type) * MIN((src)->xnum, (dest)->xnum)); \
memcpy((dest)->bg_colors, (src)->bg_colors, sizeof(color_type) * MIN((src)->xnum, (dest)->xnum)); \
memcpy((dest)->decoration_fg, (src)->decoration_fg, sizeof(color_type) * MIN((src)->xnum, (dest)->xnum)); \
memcpy((dest)->combining_chars, (src)->combining_chars, sizeof(combining_type) * MIN((src)->xnum, (dest)->xnum));
#define CLEAR_LINE(l, at, num) \
for (index_type i = (at); i < (num); i++) (l)->chars[i] = (1 << ATTRS_SHIFT) | 32; \
memset((l)->colors, (at), (num) * sizeof(color_type)); \
memset((l)->decoration_fg, (at), (num) * sizeof(decoration_type)); \
memset((l)->combining_chars, (at), (num) * sizeof(combining_type));
#define COLORS_TO_CURSOR(col, c) \
c->fg = col & COL_MASK; c->bg = (col >> COL_SHIFT)
#define CLEAR_LINE(l, num) \
for (index_type i = 0; i < (num); i++) (l)->chars[i] = (1 << ATTRS_SHIFT) | 32; \
memset((l)->fg_colors, 0, (num) * sizeof(color_type)); \
memset((l)->bg_colors, 0, (num) * sizeof(color_type)); \
memset((l)->decoration_fg, 0, (num) * sizeof(color_type)); \
memset((l)->combining_chars, 0, (num) * sizeof(combining_type));
#define METHOD(name, arg_type) {#name, (PyCFunction)name, arg_type, name##_doc},
@ -145,8 +143,9 @@ typedef struct {
PyObject_HEAD
char_type *chars;
color_type *colors;
decoration_type *decoration_fg;
color_type *fg_colors;
color_type *bg_colors;
color_type *decoration_fg;
combining_type *combining_chars;
index_type xnum, ynum;
bool continued;
@ -166,8 +165,9 @@ typedef struct {
// Pointers into buf
char_type *chars;
color_type *colors;
decoration_type *decoration_fg;
color_type *fg_colors;
color_type *bg_colors;
color_type *decoration_fg;
combining_type *combining_chars;
} LineBuf;
PyTypeObject LineBuf_Type;

View File

@ -72,8 +72,9 @@ init_line(HistoryBuf *self, index_type num, Line *l) {
uint8_t *start_ptr = start_of(self, num);
l->continued = *start_ptr;
l->chars = (char_type*)(start_ptr + 1);
l->colors = (color_type*)(l->chars + self->xnum);
l->decoration_fg = (decoration_type*)(l->colors + self->xnum);
l->fg_colors = (color_type*)(l->chars + self->xnum);
l->bg_colors = (color_type*)(l->fg_colors + self->xnum);
l->decoration_fg = (color_type*)(l->bg_colors + self->xnum);
l->combining_chars = (combining_type*)(l->decoration_fg + self->xnum);
}

View File

@ -63,8 +63,9 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
Py_CLEAR(self);
} else {
self->chars = (char_type*)self->buf;
self->colors = (color_type*)(self->chars + self->block_size);
self->decoration_fg = (decoration_type*)(self->colors + self->block_size);
self->fg_colors = (color_type*)(self->chars + self->block_size);
self->bg_colors = (color_type*)(self->fg_colors + self->block_size);
self->decoration_fg = (color_type*)(self->bg_colors + self->block_size);
self->combining_chars = (combining_type*)(self->decoration_fg + self->block_size);
self->line->xnum = xnum;
for(index_type i = 0; i < ynum; i++) {
@ -89,7 +90,8 @@ dealloc(LineBuf* self) {
#define INIT_LINE(lb, l, ynum) \
(l)->chars = (lb)->chars + (ynum) * (lb)->xnum; \
(l)->colors = (lb)->colors + (ynum) * (lb)->xnum; \
(l)->fg_colors = (lb)->fg_colors + (ynum) * (lb)->xnum; \
(l)->bg_colors = (lb)->bg_colors + (ynum) * (lb)->xnum; \
(l)->decoration_fg = (lb)->decoration_fg + (ynum) * (lb)->xnum; \
(l)->combining_chars = (lb)->combining_chars + (ynum) * (lb)->xnum;
@ -150,19 +152,22 @@ static inline int
allocate_line_storage(Line *line, bool initialize) {
if (initialize) {
line->chars = PyMem_Calloc(line->xnum, sizeof(char_type));
line->colors = PyMem_Calloc(line->xnum, sizeof(color_type));
line->decoration_fg = PyMem_Calloc(line->xnum, sizeof(decoration_type));
line->fg_colors = PyMem_Calloc(line->xnum, sizeof(color_type));
line->bg_colors = PyMem_Calloc(line->xnum, sizeof(color_type));
line->decoration_fg = PyMem_Calloc(line->xnum, sizeof(color_type));
line->combining_chars = PyMem_Calloc(line->xnum, sizeof(combining_type));
for (index_type i = 0; i < line->xnum; i++) line->chars[i] = (1 << ATTRS_SHIFT) | 32;
} else {
line->chars = PyMem_Malloc(line->xnum * sizeof(char_type));
line->colors = PyMem_Malloc(line->xnum * sizeof(color_type));
line->decoration_fg = PyMem_Malloc(line->xnum * sizeof(decoration_type));
line->fg_colors = PyMem_Malloc(line->xnum * sizeof(color_type));
line->bg_colors = PyMem_Malloc(line->xnum * sizeof(color_type));
line->decoration_fg = PyMem_Malloc(line->xnum * sizeof(color_type));
line->combining_chars = PyMem_Malloc(line->xnum * sizeof(combining_type));
}
if (line->chars == NULL || line->colors == NULL || line->decoration_fg == NULL || line->combining_chars == NULL) {
if (line->chars == NULL || line->fg_colors == NULL || line->bg_colors == NULL || line->decoration_fg == NULL || line->combining_chars == NULL) {
PyMem_Free(line->chars); line->chars = NULL;
PyMem_Free(line->colors); line->colors = NULL;
PyMem_Free(line->fg_colors); line->fg_colors = NULL;
PyMem_Free(line->bg_colors); line->bg_colors = NULL;
PyMem_Free(line->decoration_fg); line->decoration_fg = NULL;
PyMem_Free(line->combining_chars); line->combining_chars = NULL;
PyErr_NoMemory();
@ -210,7 +215,7 @@ copy_line_to(LineBuf *self, PyObject *args) {
void linebuf_clear_line(LineBuf *self, index_type y) {
Line l;
INIT_LINE(self, &l, self->line_map[y]);
CLEAR_LINE(&l, 0, self->xnum);
CLEAR_LINE(&l, self->xnum);
self->continued_map[y] = 0;
}
@ -295,7 +300,7 @@ void linebuf_insert_lines(LineBuf *self, unsigned int num, unsigned int y, unsig
Line l;
for (i = y; i < y + num; i++) {
INIT_LINE(self, &l, self->line_map[i]);
CLEAR_LINE(&l, 0, self->xnum);
CLEAR_LINE(&l, self->xnum);
self->continued_map[i] = 0;
}
}
@ -330,7 +335,7 @@ linebuf_delete_lines(LineBuf *self, index_type num, index_type y, index_type bot
Line l;
for (i = ylimit - num; i < ylimit; i++) {
INIT_LINE(self, &l, self->line_map[i]);
CLEAR_LINE(&l, 0, self->xnum);
CLEAR_LINE(&l, self->xnum);
self->continued_map[i] = 0;
}
}

View File

@ -17,7 +17,8 @@ static void
dealloc(Line* self) {
if (self->needs_free) {
PyMem_Free(self->chars);
PyMem_Free(self->colors);
PyMem_Free(self->fg_colors);
PyMem_Free(self->bg_colors);
PyMem_Free(self->decoration_fg);
PyMem_Free(self->combining_chars);
}
@ -170,9 +171,8 @@ line_as_ansi(Line *self, Py_UCS4 *buf, index_type buflen) {
WRITE_SGR(0); break;
}
}
color_type col = self->colors[pos];
CHECK_COLOR(fg, col & COL_MASK, 38);
CHECK_COLOR(bg, col >> COL_SHIFT, 48);
CHECK_COLOR(fg, self->fg_colors[pos], 38);
CHECK_COLOR(bg, self->bg_colors[pos], 48);
CHECK_COLOR(decoration_fg, self->decoration_fg[pos], DECORATION_FG_CODE);
WRITE_CH(ch);
char_type cc = self->combining_chars[pos];
@ -226,15 +226,6 @@ width(Line *self, PyObject *val) {
return PyLong_FromUnsignedLong((unsigned long) (attrs & WIDTH_MASK));
}
static PyObject*
basic_cell_data(Line *self, PyObject *val) {
#define basic_cell_data_doc "basic_cell_data(x) -> ch, attrs, colors"
unsigned long x = PyLong_AsUnsignedLong(val);
if (x >= self->xnum) { PyErr_SetString(PyExc_ValueError, "Out of bounds"); return NULL; }
char_type ch = self->chars[x];
return Py_BuildValue("IBK", (unsigned int)(ch & CHAR_MASK), (unsigned char)(ch >> ATTRS_SHIFT), (unsigned long long)self->colors[x]);
}
void line_add_combining_char(Line *self, uint32_t ch, unsigned int x) {
combining_type c = self->combining_chars[x];
if (c & CC_MASK) self->combining_chars[x] = (c & CC_MASK) | ( (ch & CC_MASK) << CC_SHIFT );
@ -279,12 +270,13 @@ set_text(Line* self, PyObject *args) {
return NULL;
}
attrs = CURSOR_TO_ATTRS(cursor, 1);
color_type col = (cursor->fg & COL_MASK) | ((color_type)(cursor->bg & COL_MASK) << COL_SHIFT);
decoration_type dfg = cursor->decoration_fg & COL_MASK;
color_type fg = (cursor->fg & COL_MASK), bg = cursor->bg & COL_MASK;
color_type dfg = cursor->decoration_fg & COL_MASK;
for (index_type i = cursor->x; offset < limit && i < self->xnum; i++, offset++) {
self->chars[i] = (PyUnicode_READ(kind, buf, offset) & CHAR_MASK) | attrs;
self->colors[i] = col;
self->fg_colors[i] = fg;
self->bg_colors[i] = bg;
self->decoration_fg[i] = dfg;
self->combining_chars[i] = 0;
}
@ -307,7 +299,7 @@ cursor_from(Line* self, PyObject *args) {
ans->x = x; ans->y = y;
char_type attrs = self->chars[x] >> ATTRS_SHIFT;
ATTRS_TO_CURSOR(attrs, ans);
COLORS_TO_CURSOR(self->colors[x], ans);
ans->fg = self->fg_colors[x]; ans->bg = self->bg_colors[x];
ans->decoration_fg = self->decoration_fg[x] & COL_MASK;
return (PyObject*)ans;
@ -335,8 +327,8 @@ clear_text(Line* self, PyObject *args) {
void
line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num, bool clear_char) {
char_type attrs = CURSOR_TO_ATTRS(cursor, 1);
color_type col = (cursor->fg & COL_MASK) | ((color_type)(cursor->bg & COL_MASK) << COL_SHIFT);
decoration_type dfg = cursor->decoration_fg & COL_MASK;
color_type fg = (cursor->fg & COL_MASK), bg = (cursor->bg & COL_MASK);
color_type dfg = cursor->decoration_fg & COL_MASK;
if (!clear_char) attrs = ((attrs >> ATTRS_SHIFT) & ~WIDTH_MASK) << ATTRS_SHIFT;
for (index_type i = at; i < self->xnum && i < at + num; i++) {
@ -347,7 +339,7 @@ line_apply_cursor(Line *self, Cursor *cursor, unsigned int at, unsigned int num,
char_type w = ((self->chars[i] >> ATTRS_SHIFT) & WIDTH_MASK) << ATTRS_SHIFT;
self->chars[i] = (self->chars[i] & CHAR_MASK) | attrs | w;
}
self->colors[i] = col;
self->fg_colors[i] = fg; self->bg_colors[i] = bg;
self->decoration_fg[i] = dfg;
}
}
@ -407,7 +399,8 @@ line_set_char(Line *self, unsigned int at, uint32_t ch, unsigned int width, Curs
attrs = (((self->chars[at] >> ATTRS_SHIFT) & ~3) | (width & 3)) << ATTRS_SHIFT;
} else {
attrs = CURSOR_TO_ATTRS(cursor, width & 3);
self->colors[at] = (cursor->fg & COL_MASK) | ((color_type)(cursor->bg & COL_MASK) << COL_SHIFT);
self->fg_colors[at] = (cursor->fg & COL_MASK);
self->bg_colors[at] = (cursor->bg & COL_MASK);
self->decoration_fg[at] = cursor->decoration_fg & COL_MASK;
}
self->chars[at] = (ch & CHAR_MASK) | attrs;
@ -449,8 +442,9 @@ __len__(PyObject *self) {
static int __eq__(Line *a, Line *b) {
return a->xnum == b->xnum && \
memcmp(a->chars, b->chars, sizeof(char_type) * a->xnum) == 0 && \
memcmp(a->colors, b->colors, sizeof(color_type) * a->xnum) == 0 && \
memcmp(a->decoration_fg, b->decoration_fg, sizeof(decoration_type) * a->xnum) == 0 && \
memcmp(a->fg_colors, b->fg_colors, sizeof(color_type) * a->xnum) == 0 && \
memcmp(a->bg_colors, b->bg_colors, sizeof(color_type) * a->xnum) == 0 && \
memcmp(a->decoration_fg, b->decoration_fg, sizeof(color_type) * a->xnum) == 0 && \
memcmp(a->combining_chars, b->combining_chars, sizeof(combining_type) * a->xnum) == 0;
}
@ -483,7 +477,6 @@ static PyMethodDef methods[] = {
METHOD(as_ansi, METH_NOARGS)
METHOD(is_continued, METH_NOARGS)
METHOD(width, METH_O)
METHOD(basic_cell_data, METH_O)
{NULL} /* Sentinel */
};
@ -522,7 +515,8 @@ copy_char(Line* self, PyObject *args) {
return NULL;
}
to->chars[dest] = self->chars[src];
to->colors[dest] = self->colors[src];
to->fg_colors[dest] = self->fg_colors[src];
to->bg_colors[dest] = self->bg_colors[src];
to->decoration_fg[dest] = self->decoration_fg[src];
to->combining_chars[dest] = self->combining_chars[src];
Py_RETURN_NONE;

View File

@ -43,8 +43,9 @@
static inline void copy_range(Line *src, index_type src_at, Line* dest, index_type dest_at, index_type num) {
memcpy(dest->chars + dest_at, src->chars + src_at, num * sizeof(char_type));
memcpy(dest->colors + dest_at, src->colors + src_at, num * sizeof(color_type));
memcpy(dest->decoration_fg + dest_at, src->decoration_fg + src_at, num * sizeof(decoration_type));
memcpy(dest->fg_colors + dest_at, src->fg_colors + src_at, num * sizeof(color_type));
memcpy(dest->bg_colors + dest_at, src->bg_colors + src_at, num * sizeof(color_type));
memcpy(dest->decoration_fg + dest_at, src->decoration_fg + src_at, num * sizeof(color_type));
memcpy(dest->combining_chars + dest_at, src->combining_chars + src_at, num * sizeof(combining_type));
}

View File

@ -160,8 +160,8 @@ update_cell_range_data(ScreenModes *modes, SpriteMap *self, Line *line, unsigned
data[offset] = sp->x;
data[offset+1] = sp->y;
data[offset+2] = sp->z;
data[offset+(reverse ? 4 : 3)] = to_color(color_profile, line->colors[i] & COL_MASK, default_fg);
data[offset+(reverse ? 3 : 4)] = to_color(color_profile, line->colors[i] >> COL_SHIFT, default_bg);
data[offset+(reverse ? 4 : 3)] = to_color(color_profile, line->fg_colors[i] & COL_MASK, default_fg);
data[offset+(reverse ? 3 : 4)] = to_color(color_profile, line->bg_colors[i] & COL_MASK, default_bg);
unsigned int decoration_fg = to_color(color_profile, line->decoration_fg[i] & COL_MASK, data[offset+3]);
data[offset+5] = (decoration_fg & COL_MASK) | (decoration << 24) | (strikethrough << 26);
previous_ch = ch; previous_width = (attrs) & WIDTH_MASK;