Store sprites in an RGBA texture
Needed to support color emoji
This commit is contained in:
parent
b8093d6b83
commit
9cda51b5a8
@ -31,6 +31,7 @@ typedef unsigned long long id_type;
|
||||
typedef uint32_t char_type;
|
||||
typedef uint32_t color_type;
|
||||
typedef uint32_t combining_type;
|
||||
typedef uint32_t pixel;
|
||||
typedef unsigned int index_type;
|
||||
typedef uint16_t sprite_index;
|
||||
typedef uint16_t attrs_type;
|
||||
@ -127,6 +128,10 @@ typedef enum MouseShapes { BEAM, HAND, ARROW } MouseShape;
|
||||
#define END_ALLOW_UNUSED_RESULT _Pragma("GCC diagnostic pop")
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint32_t left, top, right, bottom;
|
||||
} Region;
|
||||
|
||||
typedef struct {
|
||||
char_type ch;
|
||||
color_type fg, bg, decoration_fg;
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
#define MAX_NUM_EXTRA_GLYPHS 8
|
||||
|
||||
typedef uint16_t glyph_index;
|
||||
typedef void (*send_sprite_to_gpu_func)(unsigned int, unsigned int, unsigned int, uint8_t*);
|
||||
typedef void (*send_sprite_to_gpu_func)(unsigned int, unsigned int, unsigned int, pixel*);
|
||||
send_sprite_to_gpu_func current_send_sprite_to_gpu = NULL;
|
||||
static PyObject *python_send_to_gpu_impl = NULL;
|
||||
extern PyTypeObject Line_Type;
|
||||
@ -261,15 +261,15 @@ del_font(Font *f) {
|
||||
}
|
||||
|
||||
static unsigned int cell_width = 0, cell_height = 0, baseline = 0, underline_position = 0, underline_thickness = 0;
|
||||
static uint8_t *canvas = NULL;
|
||||
static pixel *canvas = NULL;
|
||||
#define CELLS_IN_CANVAS ((MAX_NUM_EXTRA_GLYPHS + 1) * 3)
|
||||
static inline void
|
||||
clear_canvas(void) { memset(canvas, 0, CELLS_IN_CANVAS * cell_width * cell_height); }
|
||||
clear_canvas(void) { memset(canvas, 0, CELLS_IN_CANVAS * cell_width * cell_height * sizeof(pixel)); }
|
||||
|
||||
static void
|
||||
python_send_to_gpu(unsigned int x, unsigned int y, unsigned int z, uint8_t* buf) {
|
||||
python_send_to_gpu(unsigned int x, unsigned int y, unsigned int z, pixel* buf) {
|
||||
if (python_send_to_gpu_impl != NULL && python_send_to_gpu_impl != Py_None) {
|
||||
PyObject *ret = PyObject_CallFunction(python_send_to_gpu_impl, "IIIN", x, y, z, PyBytes_FromStringAndSize((const char*)buf, cell_width * cell_height));
|
||||
PyObject *ret = PyObject_CallFunction(python_send_to_gpu_impl, "IIIN", x, y, z, PyBytes_FromStringAndSize((const char*)buf, sizeof(pixel) * cell_width * cell_height));
|
||||
if (ret == NULL) PyErr_Print();
|
||||
else Py_DECREF(ret);
|
||||
}
|
||||
@ -296,7 +296,7 @@ update_cell_metrics() {
|
||||
}
|
||||
sprite_tracker_set_layout(cell_width, cell_height);
|
||||
global_state.cell_width = cell_width; global_state.cell_height = cell_height;
|
||||
free(canvas); canvas = malloc(CELLS_IN_CANVAS * cell_width * cell_height);
|
||||
free(canvas); canvas = malloc(CELLS_IN_CANVAS * cell_width * cell_height * sizeof(pixel));
|
||||
if (canvas == NULL) return PyErr_NoMemory();
|
||||
for (ssize_t i = 0, j = fonts.first_symbol_font_idx; i < (ssize_t)fonts.symbol_map_fonts_count; i++, j++) {
|
||||
CALL(j, cell_height, true);
|
||||
@ -429,6 +429,21 @@ END_ALLOW_CASE_RANGE
|
||||
|
||||
static PyObject* box_drawing_function = NULL;
|
||||
|
||||
void
|
||||
render_alpha_mask(uint8_t *alpha_mask, pixel* dest, Region *src_rect, Region *dest_rect, size_t src_stride, size_t dest_stride) {
|
||||
for (size_t sr = src_rect->top, dr = dest_rect->top; sr < src_rect->bottom && dr < dest_rect->bottom; sr++, dr++) {
|
||||
pixel *d = dest + dest_stride * dr;
|
||||
uint8_t *s = alpha_mask + src_stride * sr;
|
||||
for(size_t sc = src_rect->left, dc = dest_rect->left; sc < src_rect->right && dc < dest_rect->right; sc++, dc++) {
|
||||
pixel val = d[dc];
|
||||
uint8_t alpha = s[sc];
|
||||
#define C(shift) ((MIN(0xff, alpha + ((val >> shift) & 0xff))) << shift)
|
||||
d[dc] = C(24) | C(16) | C(8) | MIN(0xff, alpha + (val & 0xff));
|
||||
#undef C
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
render_box_cell(Cell *cell) {
|
||||
int error = 0;
|
||||
@ -445,7 +460,11 @@ render_box_cell(Cell *cell) {
|
||||
sp->rendered = true;
|
||||
PyObject *ret = PyObject_CallFunction(box_drawing_function, "I", cell->ch);
|
||||
if (ret == NULL) { PyErr_Print(); return; }
|
||||
current_send_sprite_to_gpu(sp->x, sp->y, sp->z, PyLong_AsVoidPtr(PyTuple_GET_ITEM(ret, 0)));
|
||||
uint8_t *alpha_mask = PyLong_AsVoidPtr(PyTuple_GET_ITEM(ret, 0));
|
||||
clear_canvas();
|
||||
Region r = { .right = cell_width, .bottom = cell_height };
|
||||
render_alpha_mask(alpha_mask, canvas, &r, &r, cell_width, cell_width);
|
||||
current_send_sprite_to_gpu(sp->x, sp->y, sp->z, canvas);
|
||||
Py_DECREF(ret);
|
||||
}
|
||||
|
||||
@ -476,11 +495,11 @@ set_cell_sprite(Cell *cell, SpritePosition *sp) {
|
||||
cell->sprite_x = sp->x; cell->sprite_y = sp->y; cell->sprite_z = sp->z;
|
||||
}
|
||||
|
||||
static inline uint8_t*
|
||||
static inline pixel*
|
||||
extract_cell_from_canvas(unsigned int i, unsigned int num_cells) {
|
||||
uint8_t *ans = canvas + (cell_width * cell_height * (CELLS_IN_CANVAS - 1)), *dest = ans, *src = canvas + (i * cell_width);
|
||||
pixel *ans = canvas + (cell_width * cell_height * (CELLS_IN_CANVAS - 1)), *dest = ans, *src = canvas + (i * cell_width);
|
||||
unsigned int stride = cell_width * num_cells;
|
||||
for (unsigned int r = 0; r < cell_height; r++, dest += cell_width, src += stride) memcpy(dest, src, cell_width);
|
||||
for (unsigned int r = 0; r < cell_height; r++, dest += cell_width, src += stride) memcpy(dest, src, cell_width * sizeof(pixel));
|
||||
return ans;
|
||||
}
|
||||
|
||||
@ -504,7 +523,7 @@ render_group(unsigned int num_cells, unsigned int num_glyphs, Cell *cells, hb_gl
|
||||
for (unsigned int i = 0; i < num_cells; i++) {
|
||||
sprite_position[i]->rendered = true;
|
||||
set_cell_sprite(cells + i, sprite_position[i]);
|
||||
uint8_t *buf = num_cells == 1 ? canvas : extract_cell_from_canvas(i, num_cells);
|
||||
pixel *buf = num_cells == 1 ? canvas : extract_cell_from_canvas(i, num_cells);
|
||||
current_send_sprite_to_gpu(sprite_position[i]->x, sprite_position[i]->y, sprite_position[i]->z, buf);
|
||||
}
|
||||
|
||||
@ -640,8 +659,8 @@ shape_run(Cell *first_cell, index_type num_cells, Font *font) {
|
||||
unsigned int num_glyphs = shape(first_cell, num_cells, font->hb_font, &info, &positions);
|
||||
#if 0
|
||||
// You can also generate this easily using hb-shape --show-flags --show-extents --cluster-level=1 --shapers=ot /path/to/font/file text
|
||||
hb_buffer_serialize_glyphs(harfbuzz_buffer, 0, num_glyphs, (char*)canvas, CELLS_IN_CANVAS * cell_width * cell_height, NULL, font->hb_font, HB_BUFFER_SERIALIZE_FORMAT_TEXT, HB_BUFFER_SERIALIZE_FLAG_DEFAULT | HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS | HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS);
|
||||
printf("\n%s\n", canvas);
|
||||
hb_buffer_serialize_glyphs(harfbuzz_buffer, 0, num_glyphs, (char*)canvas, sizeof(pixel) * CELLS_IN_CANVAS * cell_width * cell_height, NULL, font->hb_font, HB_BUFFER_SERIALIZE_FORMAT_TEXT, HB_BUFFER_SERIALIZE_FLAG_DEFAULT | HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS | HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS);
|
||||
printf("\n%s\n", (char*)canvas);
|
||||
clear_canvas();
|
||||
#endif
|
||||
unsigned int run_pos = 0, cell_pos = 0, num_group_glyphs, num_group_cells;
|
||||
@ -815,7 +834,11 @@ send_prerendered_sprites(PyObject UNUSED *s, PyObject *args) {
|
||||
x = sprite_tracker.x; y = sprite_tracker.y; z = sprite_tracker.z;
|
||||
do_increment(&error);
|
||||
if (error != 0) { sprite_map_set_error(error); return NULL; }
|
||||
current_send_sprite_to_gpu(x, y, z, PyLong_AsVoidPtr(PyTuple_GET_ITEM(args, i)));
|
||||
uint8_t *alpha_mask = PyLong_AsVoidPtr(PyTuple_GET_ITEM(args, i));
|
||||
clear_canvas();
|
||||
Region r = { .right = cell_width, .bottom = cell_height };
|
||||
render_alpha_mask(alpha_mask, canvas, &r, &r, cell_width, cell_width);
|
||||
current_send_sprite_to_gpu(x, y, z, canvas);
|
||||
}
|
||||
return Py_BuildValue("H", x);
|
||||
}
|
||||
@ -839,18 +862,41 @@ test_render_line(PyObject UNUSED *self, PyObject *args) {
|
||||
|
||||
static PyObject*
|
||||
concat_cells(PyObject UNUSED *self, PyObject *args) {
|
||||
// Concatenate cells returning RGBA data
|
||||
unsigned int cell_width, cell_height;
|
||||
int is_32_bit;
|
||||
PyObject *cells;
|
||||
if (!PyArg_ParseTuple(args, "IIO!", &cell_width, &cell_height, &PyTuple_Type, &cells)) return NULL;
|
||||
if (!PyArg_ParseTuple(args, "IIpO!", &cell_width, &cell_height, &is_32_bit, &PyTuple_Type, &cells)) return NULL;
|
||||
size_t num_cells = PyTuple_GET_SIZE(cells), r, c, i;
|
||||
PyObject *ans = PyBytes_FromStringAndSize(NULL, 3 * cell_width * cell_height * num_cells);
|
||||
PyObject *ans = PyBytes_FromStringAndSize(NULL, 4 * cell_width * cell_height * num_cells);
|
||||
if (ans == NULL) return PyErr_NoMemory();
|
||||
uint8_t *dest = (uint8_t*)PyBytes_AS_STRING(ans), *src;
|
||||
pixel *dest = (pixel*)PyBytes_AS_STRING(ans);
|
||||
for (r = 0; r < cell_height; r++) {
|
||||
for (c = 0; c < num_cells; c++) {
|
||||
src = ((uint8_t*)PyBytes_AS_STRING(PyTuple_GET_ITEM(cells, c))) + cell_width * r;
|
||||
for (i = 0; i < cell_width; i++, dest += 3) {
|
||||
dest[0] = src[i]; dest[1] = src[i]; dest[2] = src[i];
|
||||
void *s = ((uint8_t*)PyBytes_AS_STRING(PyTuple_GET_ITEM(cells, c)));
|
||||
if (is_32_bit) {
|
||||
pixel *src = (pixel*)s + cell_width * r;
|
||||
for (i = 0; i < cell_width; i++, dest++) {
|
||||
uint8_t *rgba = (uint8_t*)dest;
|
||||
rgba[0] = (src[i] >> 24) & 0xff;
|
||||
rgba[1] = (src[i] >> 16) & 0xff;
|
||||
rgba[2] = (src[i] >> 8) & 0xff;
|
||||
rgba[3] = src[i] & 0xff;
|
||||
// pre-multiplied, so de-multiply
|
||||
if (rgba[3]) {
|
||||
float f = 255.f / (float)rgba[3];
|
||||
rgba[0] = MAX(255.f, ((float)rgba[0] * f));
|
||||
rgba[1] = MAX(255.f, ((float)rgba[1] * f));
|
||||
rgba[2] = MAX(255.f, ((float)rgba[2] * f));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint8_t *src = (uint8_t*)s + cell_width * r;
|
||||
for (i = 0; i < cell_width; i++, dest++) {
|
||||
uint8_t *rgba = (uint8_t*)dest;
|
||||
if (src[i]) { memset(rgba, 0xff, 3); rgba[3] = src[i]; }
|
||||
else *dest = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -19,7 +19,8 @@ hb_font_t* harfbuzz_font_for_face(PyObject*);
|
||||
bool set_size_for_face(PyObject*, unsigned int, bool);
|
||||
void cell_metrics(PyObject*, unsigned int*, unsigned int*, unsigned int*, unsigned int*, unsigned int*);
|
||||
void sprite_tracker_current_layout(unsigned int *x, unsigned int *y, unsigned int *z);
|
||||
bool render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, uint8_t *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline);
|
||||
bool render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline);
|
||||
void render_alpha_mask(uint8_t *alpha_mask, pixel* dest, Region *src_rect, Region *dest_rect, size_t src_stride, size_t dest_stride);
|
||||
void render_line(Line *line);
|
||||
void sprite_tracker_set_limits(size_t max_texture_size, size_t max_array_len);
|
||||
void sprite_tracker_set_layout(unsigned int cell_width, unsigned int cell_height);
|
||||
|
||||
@ -435,7 +435,7 @@ def render_missing_glyph(buf, width, height):
|
||||
draw_vline(buf, width, vgap, height - vgap + 1, width - hgap, 0)
|
||||
|
||||
|
||||
def test_drawing(sz=32, family='monospace'):
|
||||
def test_drawing(sz=48, family='monospace'):
|
||||
from .render import display_bitmap, setup_for_testing
|
||||
from kitty.fast_data_types import concat_cells, set_send_sprite_to_gpu
|
||||
|
||||
@ -444,7 +444,7 @@ def test_drawing(sz=32, family='monospace'):
|
||||
|
||||
def join_cells(cells):
|
||||
cells = tuple(bytes(x) for x in cells)
|
||||
return concat_cells(width, height, cells)
|
||||
return concat_cells(width, height, False, cells)
|
||||
|
||||
def render_chr(ch):
|
||||
if ch in box_chars:
|
||||
@ -469,7 +469,7 @@ def test_drawing(sz=32, family='monospace'):
|
||||
rgb_data = b''.join(rows)
|
||||
width *= 32
|
||||
height *= len(rows)
|
||||
assert len(rgb_data) == width * height * 3, '{} != {}'.format(len(rgb_data), width * height * 3)
|
||||
assert len(rgb_data) == width * height * 4, '{} != {}'.format(len(rgb_data), width * height * 4)
|
||||
display_bitmap(rgb_data, width, height)
|
||||
finally:
|
||||
set_send_sprite_to_gpu(None)
|
||||
|
||||
@ -220,16 +220,17 @@ def display_bitmap(rgb_data, width, height):
|
||||
if not hasattr(display_bitmap, 'detected') and not detect_support():
|
||||
raise SystemExit('Your terminal does not support the graphics protocol')
|
||||
display_bitmap.detected = True
|
||||
with NamedTemporaryFile(delete=False) as f:
|
||||
with NamedTemporaryFile(suffix='.rgba', delete=False) as f:
|
||||
f.write(rgb_data)
|
||||
show(f.name, width, height, 24)
|
||||
assert len(rgb_data) == 4 * width * height
|
||||
show(f.name, width, height, 32)
|
||||
|
||||
|
||||
def test_render_string(text='Hello, world!', family='monospace', size=144.0, dpi=96.0):
|
||||
from kitty.fast_data_types import concat_cells, current_fonts
|
||||
|
||||
cell_width, cell_height, cells = render_string(text, family, size, dpi)
|
||||
rgb_data = concat_cells(cell_width, cell_height, tuple(cells))
|
||||
rgb_data = concat_cells(cell_width, cell_height, True, tuple(cells))
|
||||
cf = current_fonts()
|
||||
fonts = [cf['medium'].display_name()]
|
||||
fonts.extend(f.display_name() for f in cf['fallback'])
|
||||
|
||||
@ -363,57 +363,50 @@ render_bitmap(Face *self, int glyph_id, ProcessedBitmap *ans, unsigned int cell_
|
||||
}
|
||||
|
||||
static inline void
|
||||
place_bitmap_in_canvas(unsigned char *cell, ProcessedBitmap *bm, size_t cell_width, size_t cell_height, float x_offset, float y_offset, FT_Glyph_Metrics *metrics, size_t baseline) {
|
||||
place_bitmap_in_canvas(pixel *cell, ProcessedBitmap *bm, size_t cell_width, size_t cell_height, float x_offset, float y_offset, FT_Glyph_Metrics *metrics, size_t baseline) {
|
||||
// We want the glyph to be positioned inside the cell based on the bearingX
|
||||
// and bearingY values, making sure that it does not overflow the cell.
|
||||
|
||||
Region src = { .left = bm->start_x, .bottom = bm->rows, .right = bm->width }, dest = { .bottom = cell_height, .right = cell_width };
|
||||
|
||||
// Calculate column bounds
|
||||
float bearing_x = (float)metrics->horiBearingX / 64.f;
|
||||
ssize_t xoff = (ssize_t)(x_offset + bearing_x);
|
||||
size_t src_start_column = bm->start_x, dest_start_column = 0, extra;
|
||||
if (xoff < 0) src_start_column += -xoff;
|
||||
else dest_start_column = xoff;
|
||||
int32_t xoff = (ssize_t)(x_offset + bearing_x);
|
||||
uint32_t extra;
|
||||
if (xoff < 0) src.left += -xoff;
|
||||
else dest.left = xoff;
|
||||
// Move the dest start column back if the width overflows because of it
|
||||
if (dest_start_column > 0 && dest_start_column + bm->width > cell_width) {
|
||||
extra = dest_start_column + bm->width - cell_width;
|
||||
dest_start_column = extra > dest_start_column ? 0 : dest_start_column - extra;
|
||||
if (dest.left > 0 && dest.left + bm->width > cell_width) {
|
||||
extra = dest.left + bm->width - cell_width;
|
||||
dest.left = extra > dest.left ? 0 : dest.left - extra;
|
||||
}
|
||||
|
||||
// Calculate row bounds
|
||||
float bearing_y = (float)metrics->horiBearingY / 64.f;
|
||||
ssize_t yoff = (ssize_t)(y_offset + bearing_y);
|
||||
size_t src_start_row, dest_start_row;
|
||||
int32_t yoff = (ssize_t)(y_offset + bearing_y);
|
||||
if (yoff > 0 && (size_t)yoff > baseline) {
|
||||
src_start_row = 0;
|
||||
dest_start_row = 0;
|
||||
dest.top = 0;
|
||||
} else {
|
||||
src_start_row = 0;
|
||||
dest_start_row = baseline - yoff;
|
||||
dest.top = baseline - yoff;
|
||||
}
|
||||
|
||||
/* printf("x_offset: %f bearing_x: %f y_offset: %f bearing_y: %f src_start_row: %zu src_start_column: %zu dest_start_row: %zu dest_start_column: %zu bm_width: %lu bitmap_rows: %lu\n", x_offset, bearing_x, y_offset, bearing_y, src_start_row, src_start_column, dest_start_row, dest_start_column, bm->width, bm->rows); */
|
||||
|
||||
for (size_t sr = src_start_row, dr = dest_start_row; sr < bm->rows && dr < cell_height; sr++, dr++) {
|
||||
for(size_t sc = src_start_column, dc = dest_start_column; sc < bm->width && dc < cell_width; sc++, dc++) {
|
||||
uint16_t val = cell[dr * cell_width + dc];
|
||||
val = MIN(255, ((uint16_t)val + (uint16_t)bm->buf[sr * bm->stride + sc]));
|
||||
cell[dr * cell_width + dc] = val;
|
||||
}
|
||||
}
|
||||
render_alpha_mask(bm->buf, cell, &src, &dest, bm->stride, cell_width);
|
||||
}
|
||||
|
||||
static inline void
|
||||
right_shift_canvas(uint8_t *canvas, size_t width, size_t height, size_t amt) {
|
||||
uint8_t *src;
|
||||
right_shift_canvas(pixel *canvas, size_t width, size_t height, size_t amt) {
|
||||
pixel *src;
|
||||
size_t r;
|
||||
for (r = 0, src = canvas; r < height; r++, src += width) {
|
||||
memmove(src + amt, src, width - amt);
|
||||
memset(src, 0, amt);
|
||||
memmove(src + amt, src, sizeof(pixel) * (width - amt));
|
||||
memset(src, 0, sizeof(pixel) * amt);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, uint8_t *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline) {
|
||||
render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *info, hb_glyph_position_t *positions, unsigned int num_glyphs, pixel *canvas, unsigned int cell_width, unsigned int cell_height, unsigned int num_cells, unsigned int baseline) {
|
||||
Face *self = (Face*)f;
|
||||
float x = 0.f, y = 0.f, x_offset = 0.f;
|
||||
ProcessedBitmap bm;
|
||||
|
||||
@ -32,15 +32,14 @@ copy_image_sub_data(GLuint src_texture_id, GLuint dest_texture_id, unsigned int
|
||||
copy_image_warned = true;
|
||||
fprintf(stderr, "WARNING: Your system's OpenGL implementation does not have glCopyImageSubData, falling back to a slower implementation.\n");
|
||||
}
|
||||
uint8_t *src = malloc(5 * width * height * num_levels);
|
||||
size_t sz = width * height * num_levels;
|
||||
pixel *src = malloc(sz * sizeof(pixel));
|
||||
if (src == NULL) { fatal("Out of memory."); }
|
||||
uint8_t *dest = src + (4 * width * height * num_levels);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, src_texture_id);
|
||||
glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, src);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, dest_texture_id);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
for(size_t i = 0; i < width * height * num_levels; i++) dest[i] = src[4*i];
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, num_levels, GL_RED, GL_UNSIGNED_BYTE, dest);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, num_levels, GL_RGBA, GL_UNSIGNED_BYTE, src);
|
||||
free(src);
|
||||
} else {
|
||||
glCopyImageSubData(src_texture_id, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, dest_texture_id, GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, num_levels);
|
||||
@ -63,7 +62,7 @@ realloc_sprite_texture() {
|
||||
sprite_tracker_current_layout(&xnum, &ynum, &z);
|
||||
znum = z + 1;
|
||||
width = xnum * global_state.cell_width; height = ynum * global_state.cell_height;
|
||||
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_R8, width, height, znum);
|
||||
glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, width, height, znum);
|
||||
if (sprite_map.texture_id) {
|
||||
// need to re-alloc
|
||||
src_ynum = MAX(1, sprite_map.last_ynum);
|
||||
@ -86,14 +85,14 @@ ensure_sprite_map() {
|
||||
}
|
||||
|
||||
void
|
||||
send_sprite_to_gpu(unsigned int x, unsigned int y, unsigned int z, uint8_t *buf) {
|
||||
send_sprite_to_gpu(unsigned int x, unsigned int y, unsigned int z, pixel *buf) {
|
||||
unsigned int xnum, ynum, znum;
|
||||
sprite_tracker_current_layout(&xnum, &ynum, &znum);
|
||||
if ((int)znum >= sprite_map.last_num_of_layers || (znum == 0 && (int)ynum > sprite_map.last_ynum)) realloc_sprite_texture();
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, sprite_map.texture_id);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
x *= global_state.cell_width; y *= global_state.cell_height;
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, x, y, z, global_state.cell_width, global_state.cell_height, 1, GL_RED, GL_UNSIGNED_BYTE, buf);
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, x, y, z, global_state.cell_width, global_state.cell_height, 1, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, buf);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@ -165,4 +165,4 @@ void draw_cursor(CursorRenderInfo *, bool);
|
||||
void update_surface_size(int, int, uint32_t);
|
||||
void free_texture(uint32_t*);
|
||||
void send_image_to_gpu(uint32_t*, const void*, int32_t, int32_t, bool, bool);
|
||||
void send_sprite_to_gpu(unsigned int, unsigned int, unsigned int, uint8_t*);
|
||||
void send_sprite_to_gpu(unsigned int, unsigned int, unsigned int, pixel*);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user