diff --git a/kitty/graphics.c b/kitty/graphics.c index 538544c82..a96cf1053 100644 --- a/kitty/graphics.c +++ b/kitty/graphics.c @@ -8,8 +8,88 @@ #include "graphics.h" #include "state.h" +#define REPORT_ERROR(fmt, ...) { fprintf(stderr, fmt, __VA_ARGS__); fprintf(stderr, "\n"); } + +GraphicsManager* +grman_realloc(GraphicsManager *old, index_type lines, index_type columns) { + GraphicsManager *self = (GraphicsManager *)GraphicsManager_Type.tp_alloc(&GraphicsManager_Type, 0); + self->lines = lines; self->columns = columns; + if (old == NULL) { + self->images_capacity = 64; + self->images = calloc(self->images_capacity, sizeof(Image)); + if (self->images == NULL) { + Py_CLEAR(self); return NULL; + } + } else { + self->images_capacity = old->images_capacity; self->images = old->images; self->image_count = old->image_count; + old->images = NULL; + grman_free(old); + } + return self; +} + +GraphicsManager* +grman_free(GraphicsManager* self) { + free(self->images); + Py_TYPE(self)->tp_free((PyObject*)self); + return NULL; +} + +/* static size_t internal_id_counter = 1; */ + +static void +handle_add_command(GraphicsManager UNUSED *self, const GraphicsCommand UNUSED *g, const uint8_t UNUSED *payload) { +} + +void +grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload) { + switch(g->action) { + case 't': + handle_add_command(self, g, payload); + break; + default: + REPORT_ERROR("Unknown graphics command action: %c", g->action); + break; + } +} + +void +grman_clear(GraphicsManager UNUSED *self) { + // TODO: Implement this +} + + +// Boilerplate {{{ +static PyObject * +new(PyTypeObject UNUSED *type, PyObject *args, PyObject UNUSED *kwds) { + unsigned int lines, columns; + if (!PyArg_ParseTuple(args, "II", &lines, &columns)) return NULL; + PyObject *ans = (PyObject*)grman_realloc(NULL, lines, columns); + if (ans == NULL) PyErr_NoMemory(); + return ans; +} + +static void +dealloc(GraphicsManager* self) { + grman_free(self); +} + + +PyTypeObject GraphicsManager_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "fast_data_types.GraphicsManager", + .tp_basicsize = sizeof(GraphicsManager), + .tp_dealloc = (destructor)dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "GraphicsManager", + .tp_new = new, +}; bool -init_graphics(PyObject UNUSED *m) { +init_graphics(PyObject *module) { + if (PyType_Ready(&GraphicsManager_Type) < 0) return false; + if (PyModule_AddObject(module, "GraphicsManager", (PyObject *)&GraphicsManager_Type) != 0) return false; + Py_INCREF(&GraphicsManager_Type); return true; } +// }}} diff --git a/kitty/graphics.h b/kitty/graphics.h index 5eb62e2af..16f952ae9 100644 --- a/kitty/graphics.h +++ b/kitty/graphics.h @@ -5,8 +5,7 @@ */ #pragma once -#include -#include +#include "data-types.h" typedef struct { unsigned char action, transmission_type; @@ -15,3 +14,25 @@ typedef struct { int32_t z_index; size_t payload_sz; } GraphicsCommand; + + +typedef struct { + uint32_t gl_id, client_id, width, height; + size_t internal_id, refcnt; +} Image; + + +typedef struct { + PyObject_HEAD + + index_type lines, columns; + size_t image_count, images_capacity; + Image *images; +} GraphicsManager; +PyTypeObject GraphicsManager_Type; + + +GraphicsManager* grman_realloc(GraphicsManager *, index_type lines, index_type columns); +void grman_clear(GraphicsManager*); +GraphicsManager* grman_free(GraphicsManager*); +void grman_handle_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_t *payload); diff --git a/kitty/parser.c b/kitty/parser.c index 804e2e956..bf4e690b3 100644 --- a/kitty/parser.c +++ b/kitty/parser.c @@ -677,6 +677,7 @@ parse_graphics_code(Screen *screen, PyObject UNUSED *dump_callback) { #undef U #undef A #undef I + screen_handle_graphics_command(screen, &g, payload); } static inline void diff --git a/kitty/screen.c b/kitty/screen.c index 1e8ebb9ca..f28e4bb9f 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -81,8 +81,10 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { self->main_linebuf = alloc_linebuf(lines, columns); self->alt_linebuf = alloc_linebuf(lines, columns); self->linebuf = self->main_linebuf; self->historybuf = alloc_historybuf(MAX(scrollback, lines), columns); + self->main_grman = grman_realloc(NULL, lines, columns); self->alt_grman = grman_realloc(NULL, lines, columns); + self->grman = self->main_grman; self->main_tabstops = PyMem_Calloc(2 * self->columns, sizeof(bool)); - if (self->cursor == NULL || self->main_linebuf == NULL || self->alt_linebuf == NULL || self->main_tabstops == NULL || self->historybuf == NULL || self->color_profile == NULL) { + if (self->cursor == NULL || self->main_linebuf == NULL || self->alt_linebuf == NULL || self->main_tabstops == NULL || self->historybuf == NULL || self->main_grman == NULL || self->alt_grman == NULL || self->color_profile == NULL) { Py_CLEAR(self); return NULL; } self->alt_tabstops = self->main_tabstops + self->columns * sizeof(bool); @@ -97,6 +99,7 @@ void screen_reset(Screen *self) { if (self->linebuf == self->alt_linebuf) screen_toggle_screen_buffer(self); linebuf_clear(self->linebuf, BLANK_CHAR); + grman_clear(self->grman); self->modes = empty_modes; #define RC(name) self->color_profile->overridden.name = 0 RC(default_fg); RC(default_bg); RC(cursor_color); RC(highlight_fg); RC(highlight_bg); @@ -137,6 +140,8 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) { bool is_main = self->linebuf == self->main_linebuf; index_type num_content_lines_before, num_content_lines_after; index_type num_content_lines; + + // Resize main linebuf HistoryBuf *nh = realloc_hb(self->historybuf, self->historybuf->ynum, columns); if (nh == NULL) return false; Py_CLEAR(self->historybuf); self->historybuf = nh; @@ -147,8 +152,17 @@ screen_resize(Screen *self, unsigned int lines, unsigned int columns) { n = realloc_lb(self->alt_linebuf, lines, columns, &num_content_lines_before, &num_content_lines_after, NULL); if (n == NULL) return false; Py_CLEAR(self->alt_linebuf); self->alt_linebuf = n; + GraphicsManager *g = grman_realloc(self->main_grman, lines, columns); + if (g == NULL) return false; + self->main_grman = g; + + // Resize alt linebuf + g = grman_realloc(self->alt_grman, lines, columns); + if (g == NULL) return false; + self->alt_grman = g; if (!is_main) num_content_lines = num_content_lines_after; self->linebuf = is_main ? self->main_linebuf : self->alt_linebuf; + self->grman = is_main ? self->main_grman : self->alt_grman; self->lines = lines; self->columns = columns; self->margin_top = 0; self->margin_bottom = self->lines - 1; @@ -199,6 +213,8 @@ static void dealloc(Screen* self) { pthread_mutex_destroy(&self->read_buf_lock); pthread_mutex_destroy(&self->write_buf_lock); + if (self->main_grman) { self->main_grman = grman_free(self->main_grman); } + if (self->alt_grman) { self->alt_grman = grman_free(self->alt_grman); } PyMem_RawFree(self->write_buf); Py_CLEAR(self->callbacks); Py_CLEAR(self->test_child); @@ -393,6 +409,10 @@ END_ALLOW_CASE_RANGE } } +void +screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, const uint8_t *payload) { + grman_handle_command(self->grman, cmd, payload); +} // }}} // Modes {{{ diff --git a/kitty/screen.h b/kitty/screen.h index b552b1a98..320f8c733 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -39,6 +39,7 @@ typedef struct { SavepointBuffer main_savepoints, alt_savepoints; PyObject *callbacks, *test_child; LineBuf *linebuf, *main_linebuf, *alt_linebuf; + GraphicsManager *grman, *main_grman, *alt_grman; HistoryBuf *historybuf; unsigned int history_line_added_count; bool *tabstops, *main_tabstops, *alt_tabstops; @@ -127,6 +128,7 @@ Line* screen_visual_line(Screen *self, index_type y); unsigned long screen_current_char_width(Screen *self); void screen_url_range(Screen *self, uint32_t *); void screen_mark_url(Screen *self, index_type start_x, index_type start_y, index_type end_x, index_type end_y); +void screen_handle_graphics_command(Screen *self, const GraphicsCommand *cmd, const uint8_t *payload); #define DECLARE_CH_SCREEN_HANDLER(name) void screen_##name(Screen *screen); DECLARE_CH_SCREEN_HANDLER(bell) DECLARE_CH_SCREEN_HANDLER(backspace)