#include "local.h"
static alias_InlineList _free_resources = ALIAS_INLINE_LIST_INIT(_free_resources);
static alias_InlineList _inactive_resources = ALIAS_INLINE_LIST_INIT(_inactive_resources);
static alias_InlineList _active_resources = ALIAS_INLINE_LIST_INIT(_active_resources);
static alias_Vector(struct LoadedResource *) _resources = ALIAS_VECTOR_INIT;
static uint32_t _resource_id = 1, _resource_gen = 1;
static void _free_resource(struct LoadedResource * resource) {
switch(resource->type) {
case ResourceType_Image:
BackendImage_unload(&resource->image);
break;
default:
break;
}
alias_InlineList_remove_self(&resource->list);
alias_InlineList_push(&_free_resources, &resource->list);
_resources.data[resource->id - 1] = NULL;
}
void Engine__resources_gc(void) {
struct LoadedResource * resource, * next_resource;
ALIAS_INLINE_LIST_EACH_CONTAINER_SAFE(&_inactive_resources, resource, next_resource, list) {
_free_resource(resource);
}
alias_InlineList_push_list(&_inactive_resources, &_active_resources);
_resource_gen++;
}
static struct LoadedResource * _allocate_resource(enum ResourceType type) {
struct LoadedResource * resource;
if(alias_InlineList_is_empty(&_free_resources)) {
resource = alias_malloc(alias_default_MemoryCB(), sizeof(*resource), alignof(*resource));
alias_InlineList_init(&resource->list);
resource->id = _resource_id++;
alias_Vector_space_for(&_resources, alias_default_MemoryCB(), 1);
*alias_Vector_push(&_resources) = NULL;
} else {
resource = ALIAS_INLINE_LIST_CONTAINER(alias_InlineList_pop(&_free_resources), struct LoadedResource, list);
}
alias_InlineList_push(&_active_resources, &resource->list);
resource->type = type;
resource->gen = _resource_gen;
_resources.data[resource->id - 1] = resource;
return resource;
}
void Engine__touch_resource(struct LoadedResource * resource) {
if(resource->gen != _resource_gen) {
alias_InlineList_remove_self(&resource->list);
alias_InlineList_push(&_active_resources, &resource->list);
resource->gen = _resource_gen;
}
}
struct LoadedResource * Engine__loaded_resource_by_id(uint32_t id) {
return _resources.data[id - 1];
}
struct LoadedResource * Engine__load_image(struct Image * img) {
struct LoadedResource * resource;
if(img->resource == NULL || img->resource_id != img->resource->id) {
char path[1024];
sprintf(path, sizeof(path), "assets/%s", img->path);
resource = _allocate_resource(ResourceType_Image);
BackendImage_load(&resource->image, path);
img->resource = resource;
img->resource_id = resource->id;
} else {
Engine__touch_resource(img->resource);
}
return img->resource;
}