mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-27 10:41:58 +02:00
Fix storage of window logos
Store by id not pointer since the pointers are not stable. And use two hash maps by path and by id for fast lookup.
This commit is contained in:
@@ -860,7 +860,7 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL
|
||||
#undef SCALE
|
||||
bool has_underlying_image = has_bgimage(os_window);
|
||||
WindowLogoRenderData *wl = &window->window_logo;
|
||||
if (wl->instance && wl->instance->load_from_disk_ok) {
|
||||
if (wl->id && (wl->instance = find_window_logo(global_state.all_window_logos, wl->id)) && wl->instance && wl->instance->load_from_disk_ok) {
|
||||
has_underlying_image = true;
|
||||
set_on_gpu_state(window->window_logo.instance, true);
|
||||
} else wl = NULL;
|
||||
|
||||
@@ -228,14 +228,17 @@ static bool
|
||||
set_window_logo(Window *w, const char *path, const ImageAnchorPosition pos, bool is_default) {
|
||||
bool ok = false;
|
||||
if (path && path[0]) {
|
||||
WindowLogo *wl = find_or_create_window_logo(&global_state.all_window_logos, path);
|
||||
window_logo_id_t wl = find_or_create_window_logo(global_state.all_window_logos, path);
|
||||
if (wl) {
|
||||
w->window_logo.instance = wl;
|
||||
w->window_logo.id = wl;
|
||||
w->window_logo.position = pos;
|
||||
ok = true;
|
||||
}
|
||||
} else {
|
||||
decref_window_logo(&global_state.all_window_logos, &w->window_logo.instance);
|
||||
if (w->window_logo.id) {
|
||||
decref_window_logo(global_state.all_window_logos, w->window_logo.id);
|
||||
w->window_logo.id = 0;
|
||||
}
|
||||
ok = true;
|
||||
}
|
||||
w->window_logo.using_default = is_default;
|
||||
@@ -313,7 +316,10 @@ destroy_window(Window *w) {
|
||||
Py_CLEAR(w->render_data.screen); Py_CLEAR(w->title);
|
||||
free(w->title_bar_data.buf); w->title_bar_data.buf = NULL;
|
||||
release_gpu_resources_for_window(w);
|
||||
decref_window_logo(&global_state.all_window_logos, &w->window_logo.instance);
|
||||
if (w->window_logo.id) {
|
||||
decref_window_logo(global_state.all_window_logos, w->window_logo.id);
|
||||
w->window_logo.id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1281,6 +1287,7 @@ finalize(void) {
|
||||
// the GPU driver should take care of it when the OpenGL context is
|
||||
// destroyed.
|
||||
free_bgimage(&global_state.bgimage, false);
|
||||
free_window_logo_table(&global_state.all_window_logos);
|
||||
global_state.bgimage = NULL;
|
||||
free_url_prefixes();
|
||||
free(OPT(select_by_word_characters)); OPT(select_by_word_characters) = NULL;
|
||||
@@ -1296,6 +1303,8 @@ init_state(PyObject *module) {
|
||||
#define DPI 96.0
|
||||
#endif
|
||||
global_state.default_dpi.x = DPI; global_state.default_dpi.y = DPI;
|
||||
global_state.all_window_logos = alloc_window_logo_table();
|
||||
if (!global_state.all_window_logos) { PyErr_NoMemory(); return false; }
|
||||
if (PyModule_AddFunctions(module, module_methods) != 0) return false;
|
||||
if (PyStructSequence_InitType2(&RegionType, ®ion_desc) != 0) return false;
|
||||
Py_INCREF((PyObject *) &RegionType);
|
||||
|
||||
@@ -83,6 +83,7 @@ typedef struct {
|
||||
} Options;
|
||||
|
||||
typedef struct WindowLogoRenderData {
|
||||
window_logo_id_t id;
|
||||
WindowLogo *instance;
|
||||
ImageAnchorPosition position;
|
||||
bool using_default;
|
||||
@@ -230,7 +231,7 @@ typedef struct {
|
||||
int active_drag_button;
|
||||
CloseRequest quit_request;
|
||||
bool redirect_mouse_handling;
|
||||
WindowLogo *all_window_logos;
|
||||
WindowLogoTable *all_window_logos;
|
||||
} GlobalState;
|
||||
|
||||
extern GlobalState global_state;
|
||||
|
||||
@@ -10,58 +10,93 @@
|
||||
|
||||
|
||||
typedef struct WindowLogoItem {
|
||||
WindowLogoHead
|
||||
WindowLogo wl;
|
||||
unsigned int refcnt;
|
||||
char *path;
|
||||
UT_hash_handle hh;
|
||||
window_logo_id_t id;
|
||||
UT_hash_handle hh_id;
|
||||
UT_hash_handle hh_path;
|
||||
} WindowLogoItem;
|
||||
|
||||
struct WindowLogoTable {
|
||||
WindowLogoItem *by_id, *by_path;
|
||||
};
|
||||
|
||||
static void
|
||||
free_window_logo(WindowLogoItem **head, WindowLogoItem **itemref) {
|
||||
free_window_logo(WindowLogoTable *table, WindowLogoItem **itemref) {
|
||||
WindowLogoItem *item = *itemref;
|
||||
free(item->path);
|
||||
free(item->bitmap);
|
||||
if (item->texture_id) free_texture(&item->texture_id);
|
||||
HASH_DEL(*head, item);
|
||||
free(item->wl.bitmap);
|
||||
if (item->wl.texture_id) free_texture(&item->wl.texture_id);
|
||||
HASH_DELETE(hh_id, table->by_id, item);
|
||||
HASH_DELETE(hh_path, table->by_path, item);
|
||||
free(item); itemref = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
send_logo_to_gpu(WindowLogoItem *s) {
|
||||
send_logo_to_gpu(WindowLogo *s) {
|
||||
send_image_to_gpu(&s->texture_id, s->bitmap, s->width, s->height, false, true, true, REPEAT_CLAMP);
|
||||
free(s->bitmap); s->bitmap = NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
set_on_gpu_state(WindowLogo *x, bool on_gpu) {
|
||||
WindowLogoItem *s = (WindowLogoItem*)x;
|
||||
set_on_gpu_state(WindowLogo *s, bool on_gpu) {
|
||||
if (s->load_from_disk_ok) {
|
||||
if (on_gpu) { if (!s->texture_id) send_logo_to_gpu(s); }
|
||||
else if (s->texture_id) free_texture(&s->texture_id);
|
||||
}
|
||||
}
|
||||
|
||||
WindowLogo*
|
||||
find_or_create_window_logo(WindowLogo **head_, const char *path) {
|
||||
WindowLogoItem **head = (WindowLogoItem**)head_;
|
||||
window_logo_id_t
|
||||
find_or_create_window_logo(WindowLogoTable *head, const char *path) {
|
||||
WindowLogoItem *s = NULL;
|
||||
HASH_FIND_STR(*head, path, s);
|
||||
if (s) return (WindowLogo*)s;
|
||||
unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(path);
|
||||
HASH_FIND(hh_path, head->by_path, path, _uthash_hfstr_keylen, s);
|
||||
if (s) return s->id;
|
||||
s = calloc(1, sizeof *s);
|
||||
size_t size;
|
||||
if (!s) { PyErr_NoMemory(); return NULL; }
|
||||
if (!s) { PyErr_NoMemory(); return 0; }
|
||||
s->path = strdup(path);
|
||||
if (!s->path) { free(s->bitmap); free(s); PyErr_NoMemory(); return NULL; }
|
||||
if (png_path_to_bitmap(path, &s->bitmap, &s->width, &s->height, &size)) s->load_from_disk_ok = true;
|
||||
if (!s->path) { free(s); PyErr_NoMemory(); return 0; }
|
||||
if (png_path_to_bitmap(path, &s->wl.bitmap, &s->wl.width, &s->wl.height, &size)) s->wl.load_from_disk_ok = true;
|
||||
s->refcnt++;
|
||||
HASH_ADD_KEYPTR(hh, *head, s->path, strlen(s->path), s);
|
||||
return (WindowLogo*)s;
|
||||
static window_logo_id_t idc = 0;
|
||||
s->id = ++idc;
|
||||
HASH_ADD(hh_id, head->by_id, id, sizeof(window_logo_id_t), s);
|
||||
HASH_ADD_KEYPTR(hh_path, head->by_path, s->path, strlen(s->path), s);
|
||||
return s->id;
|
||||
}
|
||||
|
||||
WindowLogo*
|
||||
find_window_logo(WindowLogoTable *table, window_logo_id_t id) {
|
||||
WindowLogoItem *s = NULL;
|
||||
HASH_FIND(hh_id, table->by_id, &id, sizeof(window_logo_id_t), s);
|
||||
return s ? &s->wl : NULL;
|
||||
}
|
||||
|
||||
void
|
||||
decref_window_logo(WindowLogo **head_, WindowLogo** logo) {
|
||||
WindowLogoItem **head = (WindowLogoItem**)head_;
|
||||
WindowLogoItem **s = (WindowLogoItem**)logo;
|
||||
if (*s) { if ((*s)->refcnt < 2) free_window_logo(head, s); else (*s)->refcnt--; }
|
||||
decref_window_logo(WindowLogoTable *table, window_logo_id_t id) {
|
||||
WindowLogoItem *s = NULL;
|
||||
HASH_FIND(hh_id, table->by_id, &id, sizeof(window_logo_id_t), s);
|
||||
if (s) {
|
||||
if (s->refcnt < 2) free_window_logo(table, &s);
|
||||
else s->refcnt--;
|
||||
}
|
||||
}
|
||||
|
||||
WindowLogoTable*
|
||||
alloc_window_logo_table(void) {
|
||||
return calloc(1, sizeof(WindowLogoTable));
|
||||
}
|
||||
|
||||
void
|
||||
free_window_logo_table(WindowLogoTable **table) {
|
||||
WindowLogoItem *current, *tmp;
|
||||
HASH_ITER(hh_id, (*table)->by_id, current, tmp) {
|
||||
HASH_DELETE(hh_id, (*table)->by_id, current);
|
||||
free_window_logo(*table, ¤t);
|
||||
}
|
||||
HASH_CLEAR(hh_path, (*table)->by_path);
|
||||
free(*table); *table = NULL;
|
||||
}
|
||||
|
||||
@@ -8,22 +8,31 @@
|
||||
|
||||
#include "kitty-uthash.h"
|
||||
|
||||
#define WindowLogoHead \
|
||||
unsigned int height, width; \
|
||||
bool load_from_disk_ok; \
|
||||
uint32_t texture_id; \
|
||||
uint8_t* bitmap;
|
||||
|
||||
typedef unsigned int window_logo_id_t;
|
||||
|
||||
typedef struct WindowLogo {
|
||||
WindowLogoHead
|
||||
unsigned int height, width;
|
||||
bool load_from_disk_ok;
|
||||
uint32_t texture_id;
|
||||
uint8_t* bitmap;
|
||||
} WindowLogo;
|
||||
|
||||
typedef struct WindowLogoTable WindowLogoTable;
|
||||
|
||||
window_logo_id_t
|
||||
find_or_create_window_logo(WindowLogoTable *table, const char *path);
|
||||
|
||||
WindowLogo*
|
||||
find_or_create_window_logo(WindowLogo **head, const char *path);
|
||||
find_window_logo(WindowLogoTable *table, window_logo_id_t id);
|
||||
|
||||
void
|
||||
decref_window_logo(WindowLogo **head, WindowLogo** logo);
|
||||
decref_window_logo(WindowLogoTable *table, window_logo_id_t id);
|
||||
|
||||
void
|
||||
set_on_gpu_state(WindowLogo *logo, bool on_gpu);
|
||||
|
||||
WindowLogoTable*
|
||||
alloc_window_logo_table(void);
|
||||
|
||||
void
|
||||
free_window_logo_table(WindowLogoTable **table);
|
||||
|
||||
Reference in New Issue
Block a user