Skip to content

Commit 5b78c73

Browse files
authored
Overlays: Reduce memory footprint and load time (#18577)
- Point to existing image when the overlay cfg reuses a path - `images` array in `input_overlay_t` holds unique `texture_image`s
1 parent 591a298 commit 5b78c73

4 files changed

Lines changed: 104 additions & 31 deletions

File tree

input/input_driver.c

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3018,6 +3018,20 @@ void input_overlay_set_alpha_mod(
30183018
}
30193019
}
30203020

3021+
static void input_overlay_free_images(input_overlay_t *ol)
3022+
{
3023+
size_t i;
3024+
3025+
if (!ol || !ol->images)
3026+
return;
3027+
3028+
for (i = 0; i < ol->num_images; i++)
3029+
image_texture_free(ol->images[i]);
3030+
3031+
free(ol->images);
3032+
ol->images = NULL;
3033+
}
3034+
30213035
static void input_overlay_free_overlays(input_overlay_t *ol)
30223036
{
30233037
size_t i;
@@ -3041,7 +3055,6 @@ void input_overlay_free_overlay(struct overlay *overlay)
30413055

30423056
for (i = 0; i < overlay->size; i++)
30433057
{
3044-
image_texture_free(&overlay->descs[i].image);
30453058
if (overlay->descs[i].eightway_config)
30463059
free(overlay->descs[i].eightway_config);
30473060
overlay->descs[i].eightway_config = NULL;
@@ -3053,7 +3066,6 @@ void input_overlay_free_overlay(struct overlay *overlay)
30533066
if (overlay->descs)
30543067
free(overlay->descs);
30553068
overlay->descs = NULL;
3056-
image_texture_free(&overlay->image);
30573069
}
30583070

30593071
/**
@@ -3067,6 +3079,8 @@ static void input_overlay_free(input_overlay_t *ol)
30673079
if (!ol)
30683080
return;
30693081

3082+
input_overlay_free_images(ol);
3083+
30703084
input_overlay_free_overlays(ol);
30713085

30723086
if (ol->iface && ol->iface->enable)
@@ -5415,6 +5429,25 @@ void input_overlay_check_mouse_cursor(void)
54155429
}
54165430
}
54175431

5432+
static void input_overlay_loaded_move_images(input_overlay_t *ol,
5433+
struct string_list *image_list)
5434+
{
5435+
size_t i;
5436+
5437+
ol->images = malloc(ol->num_images * sizeof(struct texture_image *));
5438+
5439+
if (!ol->images)
5440+
{
5441+
for (i = 0; i < ol->num_images; i++)
5442+
image_texture_free(image_list->elems[i].attr.p);
5443+
ol->num_images = 0;
5444+
RARCH_ERR("[Overlay] Couldn't allocate images array.\n");
5445+
}
5446+
5447+
for (i = 0; i < ol->num_images; i++)
5448+
ol->images[i] = (struct texture_image*)image_list->elems[i].attr.p;
5449+
}
5450+
54185451
/* task_data = overlay_task_data_t* */
54195452
static void input_overlay_loaded(retro_task_t *task,
54205453
void *task_data, void *user_data, const char *err)
@@ -5436,6 +5469,7 @@ static void input_overlay_loaded(retro_task_t *task,
54365469
ol->size = data->size;
54375470
ol->active = data->active;
54385471
ol->path = data->overlay_path;
5472+
ol->num_images = data->image_list->size;
54395473
ol->next_index = (unsigned)((ol->index + 1) % ol->size);
54405474
ol->flags |= INPUT_OVERLAY_ALIVE;
54415475
if (data->flags & OVERLAY_LOADER_IS_OSK)
@@ -5444,6 +5478,10 @@ static void input_overlay_loaded(retro_task_t *task,
54445478
overlay_types = data->overlay_types;
54455479
#endif
54465480

5481+
if (ol->num_images > 0)
5482+
input_overlay_loaded_move_images(ol, data->image_list);
5483+
string_list_free(data->image_list);
5484+
54475485
free(data);
54485486

54495487
/* Due to the asynchronous nature of overlay loading

input/input_overlay.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,9 @@ struct input_overlay
384384
const video_overlay_interface_t *iface;
385385
input_overlay_state_t overlay_state;
386386
input_overlay_pointer_state_t pointer_state;
387+
struct texture_image **images;
387388

389+
size_t num_images;
388390
size_t index;
389391
size_t size;
390392

@@ -435,6 +437,7 @@ typedef struct
435437
char *overlay_path;
436438
struct overlay *overlays;
437439
struct overlay *active;
440+
struct string_list *image_list;
438441
size_t size;
439442
uint16_t overlay_types;
440443
uint8_t flags;

libretro-common/include/lists/string_list.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ struct string_list
5959
*
6060
* Searches for an element (@elem) inside the string list.
6161
*
62-
* @return Number of elements found, otherwise 0.
62+
* @return 1-based index if element could be found, otherwise 0.
6363
*/
6464
int string_list_find_elem(const struct string_list *list, const char *elem);
6565

tasks/task_overlay.c

Lines changed: 60 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ struct overlay_loader
4040
char *overlay_path;
4141
struct overlay *overlays;
4242
struct overlay *active;
43+
struct string_list *image_list;
4344

4445
size_t resolve_pos;
4546
unsigned size;
@@ -62,10 +63,41 @@ static void task_overlay_image_done(struct overlay *overlay)
6263
overlay->pos_increment = (overlay->size / 2) ? ((unsigned)(overlay->size / 2)) : 8;
6364
}
6465

66+
static bool task_overlay_load_image_texture(
67+
overlay_loader_t *loader,
68+
struct overlay *overlay,
69+
struct texture_image *image,
70+
const char *full_path,
71+
const char *rel_path)
72+
{
73+
int img_idx = string_list_find_elem(loader->image_list, rel_path) - 1;
74+
75+
/* Load image if unique. Copy existing texture_image if not */
76+
if (img_idx == -1)
77+
{
78+
union string_list_elem_attr attr;
79+
80+
image->supports_rgba =
81+
(loader->flags & OVERLAY_LOADER_RGBA_SUPPORT) ? true : false;
82+
83+
if (!image_texture_load(image, full_path))
84+
return false;
85+
86+
attr.p = (void*)image;
87+
string_list_append(loader->image_list, rel_path, attr);
88+
}
89+
else
90+
*image = *((struct texture_image*)loader->image_list->elems[img_idx].attr.p);
91+
92+
overlay->load_images[overlay->load_images_size++] = *image;
93+
94+
return true;
95+
}
96+
6597
static void task_overlay_load_desc_image(
6698
overlay_loader_t *loader,
6799
struct overlay_desc *desc,
68-
struct overlay *input_overlay,
100+
struct overlay *overlay,
69101
unsigned ol_idx, unsigned desc_idx)
70102
{
71103
char overlay_desc_image_key[32];
@@ -81,22 +113,16 @@ static void task_overlay_load_desc_image(
81113
if (config_get_path(conf, overlay_desc_image_key,
82114
image_path, sizeof(image_path)))
83115
{
84-
struct texture_image image_tex;
85116
char path[PATH_MAX_LENGTH];
86117
fill_pathname_resolve_relative(path, loader->overlay_path,
87118
image_path, sizeof(path));
88119

89-
image_tex.supports_rgba = (loader->flags & OVERLAY_LOADER_RGBA_SUPPORT) ? true : false;
90-
91-
if (image_texture_load(&image_tex, path))
92-
{
93-
input_overlay->load_images[input_overlay->load_images_size++] = image_tex;
94-
desc->image = image_tex;
95-
desc->image_index = input_overlay->load_images_size - 1;
96-
}
120+
if (task_overlay_load_image_texture(loader, overlay, &desc->image,
121+
path, image_path))
122+
desc->image_index = overlay->load_images_size - 1;
97123
}
98124

99-
input_overlay->pos ++;
125+
overlay->pos ++;
100126
}
101127

102128
static void task_overlay_redefine_eightway_direction(
@@ -781,7 +807,6 @@ static void task_overlay_deferred_load(retro_task_t *task)
781807

782808
if (!string_is_empty(overlay->config.paths.path))
783809
{
784-
struct texture_image image_tex;
785810
char overlay_resolved_path[PATH_MAX_LENGTH];
786811

787812
overlay_resolved_path[0] = '\0';
@@ -790,19 +815,14 @@ static void task_overlay_deferred_load(retro_task_t *task)
790815
loader->overlay_path,
791816
overlay->config.paths.path, sizeof(overlay_resolved_path));
792817

793-
image_tex.supports_rgba =
794-
(loader->flags & OVERLAY_LOADER_RGBA_SUPPORT) ? true : false;
795-
796-
if (!image_texture_load(&image_tex, overlay_resolved_path))
818+
if (!task_overlay_load_image_texture(loader, overlay, &overlay->image,
819+
overlay_resolved_path, overlay->config.paths.path))
797820
{
798821
RARCH_ERR("[Overlay] Failed to load image: \"%s\".\n",
799822
overlay_resolved_path);
800823
loader->loading_status = OVERLAY_IMAGE_TRANSFER_ERROR;
801824
goto error;
802825
}
803-
804-
overlay->load_images[overlay->load_images_size++] = image_tex;
805-
overlay->image = image_tex;
806826
}
807827

808828
config_get_array(conf, overlay->config.names.key,
@@ -1008,19 +1028,16 @@ static void task_overlay_free(retro_task_t *task)
10081028
{
10091029
unsigned i;
10101030
overlay_loader_t *loader = (overlay_loader_t*)task->state;
1011-
struct overlay *overlay = &loader->overlays[loader->pos];
10121031
uint8_t flg = task_get_flags(task);
10131032

10141033
if ((flg & RETRO_TASK_FLG_CANCELLED) > 0)
10151034
{
10161035
if (loader->overlay_path)
10171036
free(loader->overlay_path);
10181037

1019-
for (i = 0; i < overlay->load_images_size; i++)
1020-
{
1021-
struct texture_image *ti = &overlay->load_images[i];
1022-
image_texture_free(ti);
1023-
}
1038+
for (i = 0; i < loader->image_list->size; i++)
1039+
image_texture_free(loader->image_list->elems[i].attr.p);
1040+
string_list_free(loader->image_list);
10241041

10251042
for (i = 0; i < loader->size; i++)
10261043
input_overlay_free_overlay(&loader->overlays[i]);
@@ -1074,6 +1091,7 @@ static void task_overlay_handler(retro_task_t *task)
10741091
data->flags = loader->flags;
10751092
data->overlay_types = loader->overlay_types;
10761093
data->overlay_path = loader->overlay_path;
1094+
data->image_list = loader->image_list;
10771095

10781096
task_set_data(task, data);
10791097
}
@@ -1096,9 +1114,10 @@ bool task_push_overlay_load_default(
10961114
void *user_data)
10971115
{
10981116
task_finder_data_t find_data;
1099-
retro_task_t *t = NULL;
1100-
config_file_t *conf = NULL;
1101-
overlay_loader_t *loader = NULL;
1117+
retro_task_t *t = NULL;
1118+
config_file_t *conf = NULL;
1119+
overlay_loader_t *loader = NULL;
1120+
struct string_list *image_list = NULL;
11021121

11031122
if (string_is_empty(overlay_path))
11041123
return false;
@@ -1115,9 +1134,18 @@ bool task_push_overlay_load_default(
11151134
if (!loader)
11161135
return false;
11171136

1137+
image_list = string_list_new();
1138+
1139+
if (!image_list)
1140+
{
1141+
free(loader);
1142+
return false;
1143+
}
1144+
11181145
if (!(conf = config_file_new_from_path_to_string(overlay_path)))
11191146
{
11201147
free(loader);
1148+
free(image_list);
11211149
return false;
11221150
}
11231151

@@ -1126,6 +1154,7 @@ bool task_push_overlay_load_default(
11261154
/* Error - overlays variable not defined in config. */
11271155
config_file_free(conf);
11281156
free(loader);
1157+
free(image_list);
11291158
return false;
11301159
}
11311160

@@ -1136,10 +1165,12 @@ bool task_push_overlay_load_default(
11361165
{
11371166
config_file_free(conf);
11381167
free(loader);
1168+
free(image_list);
11391169
return false;
11401170
}
11411171

11421172
loader->conf = conf;
1173+
loader->image_list = image_list;
11431174
loader->state = OVERLAY_STATUS_DEFERRED_LOAD;
11441175
loader->pos_increment = (loader->size / 4) ? (loader->size / 4) : 4;
11451176

@@ -1157,6 +1188,7 @@ bool task_push_overlay_load_default(
11571188
config_file_free(conf);
11581189
free(loader->overlays);
11591190
free(loader);
1191+
free(image_list);
11601192
return false;
11611193
}
11621194

0 commit comments

Comments
 (0)