Use hashtables for resource management

This commit is contained in:
Andrei "Akari" Alexeyev 2017-02-28 19:47:47 +02:00
parent fdd4633e19
commit 18652576d6
19 changed files with 243 additions and 241 deletions

View file

@ -12,6 +12,7 @@
#include <assert.h>
#include <string.h>
#include <zlib.h>
#include <stdio.h>
typedef struct HashtableElement {
void *next;
@ -59,11 +60,18 @@ static void hashtable_delete_callback(void **vlist, void *velem, void *vht) {
delete_element(vlist, velem);
}
void hashtable_free(Hashtable *ht) {
void hashtable_unset_all(Hashtable *ht) {
for(size_t i = 0; i < ht->table_size; ++i) {
delete_all_elements_witharg((void**)(ht->table + i), hashtable_delete_callback, ht);
}
}
void hashtable_free(Hashtable *ht) {
if(!ht) {
return;
}
hashtable_unset_all(ht);
free(ht->table);
free(ht);
}
@ -180,6 +188,28 @@ void hashtable_unset_string(Hashtable *ht, const char *key) {
hashtable_unset(ht, (void*)key);
}
/*
* Misc convenience functions
*/
void* hashtable_iter_free_data(void *key, void *data, void *arg) {
free(data);
return NULL;
}
void hashtable_print_stringkeys(Hashtable *ht) {
printf("------ %p:\n", (void*)ht);
for(size_t i = 0; i < ht->table_size; ++i) {
for(HashtableElement *e = ht->table[i]; e; e = e->next) {
printf("[HT %lu] %s (%lu): %p\n", (unsigned long)i, (char*)e->key, e->hash, e->data);
}
}
}
/*
* Misc convenience functions
*/
// #define HASHTABLE_TEST
#ifdef HASHTABLE_TEST

View file

@ -27,6 +27,7 @@ void hashtable_free(Hashtable *ht);
void* hashtable_get(Hashtable *ht, void *key);
void hashtable_set(Hashtable *ht, void *key, void *data);
void hashtable_unset(Hashtable *ht, void *key);
void hashtable_unset_all(Hashtable *ht);
void* hashtable_foreach(Hashtable *ht, HTIterCallback callback, void *arg);
bool hashtable_cmpfunc_string(void *str1, void *str2);
@ -39,6 +40,10 @@ void* hashtable_get_string(Hashtable *ht, const char *key);
void hashtable_set_string(Hashtable *ht, const char *key, void *data);
void hashtable_unset_string(Hashtable *ht, const char *key);
void* hashtable_iter_free_data(void *key, void *data, void *arg);
int hashtable_test(void);
void hashtable_print_stringkeys(Hashtable *ht);
#endif

View file

@ -142,6 +142,7 @@ int main(int argc, char **argv) {
video_init();
printf("-- Video and OpenGL\n");
init_resources();
draw_loading_screen();
gamepad_init();

View file

@ -12,14 +12,14 @@
#include "taisei_err.h"
Animation *init_animation(char *filename) {
Animation *buf = create_element((void **)&resources.animations, sizeof(Animation));
Animation *init_animation(const char *filename) {
Animation *buf = malloc(sizeof(Animation));
char *beg = strstr(filename, "gfx/") + 4;
char *end = strrchr(filename, '.');
int sz = end - beg + 1;
char *name = malloc(sz);
char name[end - beg + 1];
strlcpy(name, beg, sz);
char* tok;
@ -35,31 +35,28 @@ Animation *init_animation(char *filename) {
errx(-1, "init_animation():\n!- bad 'speed' in filename '%s'", name);
buf->speed = atoi(tok);
if(buf->speed == 0)
errx(-1, "animation speed of %s == 0. relativity?", name);
if((tok = strtok(NULL, "_")) == NULL)
errx(-1, "init_animation():\n!- bad 'name' in filename '%s'", name);
buf->name = malloc(strlen(tok)+1);
memset(buf->name, 0, strlen(tok)+1);
strcpy(buf->name, tok);
char refname[strlen(tok)+1];
memset(refname, 0, strlen(tok)+1);
strcpy(refname, tok);
buf->tex = load_texture(filename);
buf->w = buf->tex->w/buf->cols;
buf->h = buf->tex->h/buf->rows;
free(name);
printf("-- initialized animation '%s'\n", buf->name);
hashtable_set_string(resources.animations, refname, buf);
printf("-- initialized animation '%s'\n", name);
return buf;
}
Animation *get_ani(char *name) {
Animation *a;
Animation *res = NULL;
for(a = resources.animations; a; a = a->next) {
if(strcmp(a->name, name) == 0) {
res = a;
}
}
Animation *get_ani(const char *name) {
Animation *res = hashtable_get_string(resources.animations, name);
if(res == NULL)
errx(-1,"get_ani():\n!- cannot load animation '%s'", name);
@ -67,16 +64,11 @@ Animation *get_ani(char *name) {
return res;
}
void delete_animation(void **anis, void *ani) {
free(((Animation *)ani)->name);
delete_element(anis, ani);
}
void delete_animations(void) {
delete_all_elements((void **)&resources.animations, delete_animation);
resources_delete_and_unset_all(resources.animations, hashtable_iter_free_data, NULL);
}
void draw_animation(float x, float y, int row, char *name) {
void draw_animation(float x, float y, int row, const char *name) {
draw_animation_p(x, y, row, get_ani(name));
}
@ -87,9 +79,6 @@ void draw_animation_p(float x, float y, int row, Animation *ani) {
float s = (float)ani->tex->w/ani->cols/ani->tex->truew;
float t = ((float)ani->tex->h)/ani->tex->trueh/(float)ani->rows;
if(ani->speed == 0)
errx(-1, "animation speed of %s == 0. relativity?", ani->name);
glPushMatrix();
if(x || y)
glTranslatef(x,y,0);

View file

@ -13,24 +13,21 @@
struct Animation;
typedef struct Animation {
struct Animation *next;
struct Animation *prev;
int rows;
int cols;
int w,h;
int w;
int h;
int speed;
char *name;
Texture *tex;
} Animation;
Animation *init_animation(char *filename);
Animation *get_ani(char *name);
Animation *init_animation(const char *filename);
Animation *get_ani(const char *name);
void delete_animations(void);
void draw_animation(float x, float y, int row, char *name);
void draw_animation(float x, float y, int row, const char *name);
void draw_animation_p(float x, float y, int row, Animation *ani);
#endif

View file

@ -114,7 +114,7 @@ void shutdown_sfx(void)
unload_mixer_if_needed();
}
Sound *load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type) {
Sound *load_sound_or_bgm(const char *filename, Hashtable *ht, sound_type_t type) {
Mix_Chunk *sound = NULL;
Mix_Music *music = NULL;
@ -138,7 +138,7 @@ Sound *load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type) {
errx(-1,"load_sound_or_bgm():\n!- incorrect sound type specified");
}
Sound *snd = create_element((void **)dest, sizeof(Sound));
Sound *snd = malloc(sizeof(Sound));
snd->type = type;
if (sound)
@ -154,26 +154,22 @@ Sound *load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type) {
++beg; // skip '/' between last path element and file name
int sz = end - beg + 1;
snd->name = malloc(sz);
if (!snd->name)
errx(-1,"load_sound_or_bgm():\n!- failed to allocate memory for sound name (is it empty?)");
strlcpy(snd->name, beg, sz);
char name[sz];
strlcpy(name, beg, sz);
printf("-- loaded '%s' as %s '%s'\n", filename, ((type==ST_SOUND) ? "SFX" : "BGM"), snd->name);
hashtable_set_string(ht, name, snd);
printf("-- loaded '%s' as %s '%s'\n", filename, ((type==ST_SOUND) ? "SFX" : "BGM"), name);
return snd;
}
Sound *load_sound(char *filename) {
return load_sound_or_bgm(filename, &resources.sounds, ST_SOUND);
Sound *load_sound(const char *filename) {
return load_sound_or_bgm(filename, resources.sounds, ST_SOUND);
}
Sound *get_snd(Sound *source, char *name) {
Sound *s, *res = NULL;
for(s = source; s; s = s->next) {
if(strcmp(s->name, name) == 0)
res = s;
}
Sound *get_snd(Hashtable *source, const char *name) {
Sound *res = hashtable_get_string(resources.sounds, name);
if(res == NULL)
warnx("get_snd():\n!- cannot find sound '%s'", name);
@ -181,7 +177,7 @@ Sound *get_snd(Sound *source, char *name) {
return res;
}
void play_sound_p(char *name, int unconditional)
void play_sound_p(const char *name, int unconditional)
{
if(config_get_int(CONFIG_NO_AUDIO) || global.frameskip) return;
@ -205,14 +201,21 @@ void set_sfx_volume(float gain)
Mix_Volume(-1, gain * MIX_MAX_VOLUME);
}
void delete_sound(void **snds, void *snd) {
#include <assert.h>
void* delete_sound(void *name, void *snd, void *arg) {
Sound *ssnd = (Sound *)snd;
free(ssnd->name);
if(ssnd->type == ST_MUSIC) Mix_FreeMusic(ssnd->music);
else Mix_FreeChunk(ssnd->sound);
delete_element(snds, snd);
if(ssnd->type == ST_MUSIC) {
Mix_FreeMusic(ssnd->music);
} else if(ssnd->type == ST_SOUND) {
Mix_FreeChunk(ssnd->sound);
}
free(snd);
return NULL;
}
void delete_sounds(void) {
delete_all_elements((void **)&resources.sounds, delete_sound);
resources_delete_and_unset_all(resources.sounds, delete_sound, NULL);
}

View file

@ -8,6 +8,9 @@
#ifndef AUDIO_H
#define AUDIO_H
#undef HAVE_MIXER
#define HAVE_MIXER
#ifdef HAVE_MIXER
#include <SDL_mixer.h>
#else
@ -15,6 +18,8 @@ typedef void Mix_Chunk;
typedef void Mix_Music;
#endif
#include "hashtable.h"
#define SNDCHAN_COUNT 100
typedef enum {
@ -25,29 +30,25 @@ typedef enum {
struct Sound;
typedef struct Sound {
struct Sound *next;
struct Sound *prev;
int lastplayframe;
sound_type_t type;
union {
Mix_Chunk *sound;
Mix_Music *music;
};
char *name;
} Sound;
Sound *load_sound(char *filename);
Sound *load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type);
Sound *load_sound(const char *filename);
Sound *load_sound_or_bgm(const char *filename, Hashtable *ht, sound_type_t type);
#define play_sound(name) play_sound_p(name, 0);
#define play_ui_sound(name) play_sound_p(name, 1);
void play_sound_p(char *name, int unconditional);
void play_sound_p(const char *name, int unconditional);
Sound *get_snd(Sound *source, char *name);
Sound *get_snd(Hashtable *source, const char *name);
void delete_sound(void **snds, void *snd);
void* delete_sound(void *name, void *snd, void *arg);
void delete_sounds(void);
void set_sfx_volume(float gain);

View file

@ -2,24 +2,24 @@
#include <stdlib.h>
#include "audio.h"
Sound* load_sound(char *filename) {
Sound* load_sound(const char *filename) {
return NULL;
}
Sound* load_sound_or_bgm(char *filename, Sound **dest, sound_type_t type) {
Sound* load_sound_or_bgm(const char *filename, Hashtable *ht, sound_type_t type) {
return NULL;
}
void play_sound_p(char *name, int unconditional) {
void play_sound_p(const char *name, int unconditional) {
return;
}
Sound* get_snd(Sound *source, char *name) {
Sound* get_snd(Hashtable *source, const char *name) {
return NULL;
}
void delete_sound(void **snds, void *snd) {
return;
void* delete_sound(void *name, void *snd, void *arg) {
return NULL;
}
void delete_sounds(void) {

View file

@ -65,17 +65,8 @@ void shutdown_bgm(void)
unload_mixer_if_needed();
}
char *get_bgm_desc(Bgm_desc *source, char *name) {
for(; source; source = source->next)
if(strcmp(source->name, name) == 0)
return source->value;
return NULL;
}
void delete_bgm_description(void **descs, void *desc) {
free(((Bgm_desc *)desc)->name);
free(((Bgm_desc *)desc)->value);
delete_element(descs, desc);
char *get_bgm_desc(char *name) {
return (char*)hashtable_get_string(resources.bgm_descriptions, name);
}
void load_bgm_descriptions(const char *path) {
@ -105,31 +96,25 @@ void load_bgm_descriptions(const char *path) {
}
*(rem++)='\0';
Bgm_desc *desc = create_element((void **)&resources.bgm_descriptions, sizeof(Bgm_desc));
desc->name = NULL;
stralloc(&desc->name, line);
desc->value = malloc(strlen(rem) + 6);
if (!desc->name || !desc->value)
{
delete_bgm_description((void**)resources.bgm_descriptions, desc);
warnx("load_bgm_description():\n!- strdup() failed");
continue;
}
strcpy(desc->value, "BGM: ");
strcat(desc->value, rem);
printf ("Music %s is now known as \"%s\".\n", desc->name, desc->value);
char *value = malloc(strlen(rem) + 6);
strcpy(value, "BGM: ");
strcat(value, rem);
hashtable_set_string(resources.bgm_descriptions, line, value);
printf("Music %s is now known as \"%s\".\n", line, value);
}
fclose(fp);
return;
}
Sound *load_bgm(char *filename) {
return load_sound_or_bgm(filename, &resources.music, ST_MUSIC);
Sound *load_bgm(const char *filename) {
return load_sound_or_bgm(filename, resources.music, ST_MUSIC);
}
void start_bgm(char *name) {
void start_bgm(const char *name) {
if(config_get_int(CONFIG_NO_MUSIC)) return;
// start_bgm(NULL) or start_bgm("") would be equivalent to stop_bgm().
@ -164,7 +149,7 @@ void start_bgm(char *name) {
if(Mix_PlayMusic(current_bgm.data->music, -1) == -1) // Start playing otherwise
printf("Failed starting BGM %s: %s.\n", current_bgm.name, Mix_GetError());
// Support drawing BGM title in game loop (only when music changed!)
if ((current_bgm.title = get_bgm_desc(resources.bgm_descriptions, current_bgm.name)) != NULL)
if ((current_bgm.title = get_bgm_desc(current_bgm.name)) != NULL)
{
current_bgm.started_at = global.frames;
// Boss BGM title color may differ from the one at beginning of stage
@ -218,6 +203,6 @@ void set_bgm_volume(float gain)
}
void delete_music(void) {
delete_all_elements((void **)&resources.bgm_descriptions, delete_bgm_description);
delete_all_elements((void **)&resources.music, delete_sound);
resources_delete_and_unset_all(resources.bgm_descriptions, hashtable_iter_free_data, NULL);
resources_delete_and_unset_all(resources.music, delete_sound, NULL);
}

View file

@ -10,14 +10,6 @@
#include "audio.h"
typedef struct Bgm_desc {
struct Bgm_desc *next;
struct Bgm_desc *prev;
char *name;
char *value;
} Bgm_desc;
struct current_bgm_t {
char *name;
char *title;
@ -28,9 +20,9 @@ struct current_bgm_t {
extern struct current_bgm_t current_bgm;
Sound *load_bgm(char *filename);
Sound *load_bgm(const char *filename);
void start_bgm(char *name);
void start_bgm(const char *name);
void stop_bgm(void);
void continue_bgm(void);
void save_bgm(void);

View file

@ -5,11 +5,11 @@
struct current_bgm_t current_bgm;
Sound *load_bgm(char *filename) {
Sound *load_bgm(const char *filename) {
return NULL;
}
void start_bgm(char *name) {
void start_bgm(const char *name) {
return;
}

View file

@ -13,7 +13,7 @@
#include <string.h>
#include <stdlib.h>
void parse_obj(char *filename, ObjFileData *data) {
static void parse_obj(const char *filename, ObjFileData *data) {
FILE *fp = fopen(filename, "rb");
char line[256];
@ -109,12 +109,12 @@ void parse_obj(char *filename, ObjFileData *data) {
fclose(fp);
}
static void bad_reference_error(char *filename, char *aux, int n) {
static void bad_reference_error(const char *filename, const char *aux, int n) {
errx(-1, "load_model():\n!- OBJ file '%s': Index %d: bad %s index reference\n", filename, n, aux);
}
Model *load_model(char *filename) {
Model *m = create_element((void **)&resources.models, sizeof(Model));
Model *load_model(const char *filename) {
Model *m = malloc(sizeof(Model));
ObjFileData data;
unsigned int i;
@ -126,8 +126,8 @@ Model *load_model(char *filename) {
char *end = strrchr(filename, '.');
int sz = end - beg + 1;
m->name = malloc(sz);
strlcpy(m->name, beg, sz);
char name[sz];
strlcpy(name, beg, sz);
parse_obj(filename, &data);
@ -170,7 +170,9 @@ Model *load_model(char *filename) {
vbo_add_verts(&_vbo, verts, data.icount);
printf("-- loaded '%s' as '%s'\n", filename, m->name);
hashtable_set_string(resources.models, name, m);
printf("-- loaded '%s' as '%s'\n", filename, name);
free(verts);
free(data.xs);
@ -180,12 +182,8 @@ Model *load_model(char *filename) {
return m;
}
Model *get_model(char *name) {
Model *m, *res = NULL;
for(m = resources.models; m; m = m->next) {
if(strcmp(m->name, name) == 0)
res = m;
}
Model *get_model(const char *name) {
Model *res = hashtable_get_string(resources.models, name);
if(res == NULL)
errx(-1,"get_model():\n!- cannot load model '%s'", name);
@ -215,17 +213,16 @@ void draw_model_p(Model *model) {
glMatrixMode(GL_MODELVIEW);
}
void draw_model(char *name) {
void draw_model(const char *name) {
draw_model_p(get_model(name));
}
void delete_model(void **models, void *model) {
free(((Model *)model)->name);
void* delete_model(void *name, void *model, void *arg) {
free(((Model *)model)->indices);
delete_element(models, model);
free(model);
return NULL;
}
void delete_models(void) { // Does not delete elements from the VBO, so doing this at runtime is leaking VBO space
delete_all_elements((void **)&resources.models, delete_model);
void delete_models(void) { // Does not delete elements from the VBO, so doing this at runtime is leaking VBO spac
resources_delete_and_unset_all(resources.models, delete_model, NULL);
}

View file

@ -12,8 +12,7 @@
typedef int IVector[3];
typedef struct ObjFileData ObjFileData;
struct ObjFileData {
typedef struct ObjFileData {
Vector *xs;
int xcount;
@ -27,27 +26,19 @@ struct ObjFileData {
int icount;
int fverts;
};
typedef struct Model Model;
struct Model {
struct Model *next;
struct Model *prev;
char *name;
} ObjFileData;
typedef struct Model {
unsigned int *indices;
int icount;
int fverts;
};
} Model;
Model *load_model(char *filename);
Model *get_model(char *name);
Model *load_model(const char *filename);
Model *get_model(const char *name);
void draw_model_p(Model *model);
void draw_model(char *name);
void draw_model(const char *name);
void delete_models(void); // Does not delete elements from the VBO, so doing this at runtime is leaking VBO space
#endif

View file

@ -76,14 +76,32 @@ static void resources_cfg_noshader_callback(ConfigIndex idx, ConfigValue v) {
}
}
static void init_hashtables(void) {
resources.textures = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.animations = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.sounds = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.music = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.shaders = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.models = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
resources.bgm_descriptions = hashtable_new_stringkeys(RES_HASHTABLE_SIZE);
}
static void free_hashtables(void) {
hashtable_free(resources.textures);
hashtable_free(resources.animations);
hashtable_free(resources.sounds);
hashtable_free(resources.music);
hashtable_free(resources.shaders);
hashtable_free(resources.models);
hashtable_free(resources.bgm_descriptions);
}
void init_resources(void) {
init_hashtables();
config_set_callback(CONFIG_NO_SHADER, resources_cfg_noshader_callback);
}
void load_resources(void) {
static bool callbacks_set_up = false;
if(!callbacks_set_up) {
config_set_callback(CONFIG_NO_SHADER, resources_cfg_noshader_callback);
callbacks_set_up = true;
}
printf("load_resources():\n");
char *path = malloc(strlen(get_prefix())+32);
@ -177,6 +195,13 @@ void free_resources(void) {
printf("-- freeing shaders\n");
delete_shaders();
}
free_hashtables();
}
void resources_delete_and_unset_all(Hashtable *ht, HTIterCallback ifunc, void *arg) {
hashtable_foreach(ht, ifunc, arg);
hashtable_unset_all(ht);
}
void draw_loading_screen(void) {

View file

@ -17,9 +17,12 @@
#include "shader.h"
#include "font.h"
#include "model.h"
#include "hashtable.h"
typedef struct Resources Resources;
#define RES_HASHTABLE_SIZE 64
typedef enum ResourceState {
RS_GfxLoaded = 1,
RS_SfxLoaded = 2,
@ -32,13 +35,13 @@ typedef enum ResourceState {
struct Resources {
ResourceState state;
Texture *textures;
Animation *animations;
Sound *sounds;
Sound *music;
Shader *shaders;
Model *models;
Bgm_desc *bgm_descriptions;
Hashtable *textures;
Hashtable *animations;
Hashtable *sounds;
Hashtable *music;
Hashtable *shaders;
Hashtable *models;
Hashtable *bgm_descriptions;
FBO fbg[2];
FBO fsec;
@ -46,8 +49,12 @@ struct Resources {
extern Resources resources;
void init_resources(void);
void load_resources(void);
void free_resources(void);
void draw_loading_screen(void);
void resources_delete_and_unset_all(Hashtable *ht, HTIterCallback ifunc, void *arg);
#endif

View file

@ -70,7 +70,7 @@ void print_program_info_log(GLuint program) {
}
}
char *read_all(char *filename, int *size) {
char *read_all(const char *filename, int *size) {
char *text;
FILE *file = fopen(filename, "r");
if(file == NULL)
@ -92,7 +92,7 @@ char *read_all(char *filename, int *size) {
return text;
}
char *copy_segment(char *text, char *delim, int *size) {
char *copy_segment(const char *text, const char *delim, int *size) {
char *seg, *beg, *end;
beg = strstr(text, delim);
@ -111,7 +111,7 @@ char *copy_segment(char *text, char *delim, int *size) {
return seg;
}
void load_shader_snippets(char *filename, char *prefix) {
void load_shader_snippets(const char *filename, const char *prefix) {
int size, vhsize = 0, vfsize = 0, fhsize = 0, ffsize = 0, ssize, prefixlen;
char *text, *vhead, *vfoot, *fhead, *ffoot;
char *sec, *name, *nend, *send;
@ -204,7 +204,7 @@ void load_shader_snippets(char *filename, char *prefix) {
free(text);
}
void load_shader_file(char *filename) {
void load_shader_file(const char *filename) {
int size;
char *text, *vtext, *ftext, *delim;
char *beg, *end, *name;
@ -234,8 +234,8 @@ void load_shader_file(char *filename) {
free(text);
}
void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *name, int nsize) {
Shader *sha = create_element((void **)&resources.shaders, sizeof(Shader));
void load_shader(const char *vheader, const char *fheader, const char *vtext, const char *ftext, const char *name, int nsize) {
Shader *sha = malloc(sizeof(Shader));
GLuint vshaderobj;
GLuint fshaderobj;
@ -251,8 +251,8 @@ void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *n
fheader = "";
}
GLchar *v_sources[] = { vheader, vtext };
GLchar *f_sources[] = { fheader, ftext };
const GLchar *v_sources[] = { vheader, vtext };
const GLchar *f_sources[] = { fheader, ftext };
GLint lengths[] = { -1, -1 };
glShaderSource(vshaderobj, 2, (const GLchar**)v_sources, lengths);
@ -274,10 +274,9 @@ void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *n
print_program_info_log(sha->prog);
sha->name = malloc(nsize);
strlcpy(sha->name, name, nsize);
cache_uniforms(sha);
hashtable_set_string(resources.shaders, name, sha);
}
void cache_uniforms(Shader *sha) {
@ -299,7 +298,7 @@ void cache_uniforms(Shader *sha) {
}
}
int uniloc(Shader *sha, char *name) {
int uniloc(Shader *sha, const char *name) {
int i;
for(i = 0; i < sha->unicount; i++)
if(strcmp(sha->uniforms[i].name, name) == 0)
@ -309,33 +308,24 @@ int uniloc(Shader *sha, char *name) {
}
Shader *get_shader(const char *name) {
Shader *s, *res = NULL;
if(config_get_int(CONFIG_NO_SHADER))
return NULL;
for(s = resources.shaders; s; s = s->next) {
if(strcmp(s->name, name) == 0)
res = s;
}
return res;
return hashtable_get_string(resources.shaders, name);
}
void delete_shader(void **shas, void *sha) {
free(((Shader *)sha)->name);
glDeleteProgram(((Shader*)sha)->prog);
void* delete_shader(void *name, void *vsha, void *arg) {
Shader *sha = vsha;
glDeleteProgram((sha)->prog);
int i;
for(i = 0; i < ((Shader *)sha)->unicount; i++)
free(((Shader *)sha)->uniforms[i].name);
for(int i = 0; i < sha->unicount; i++)
free(sha->uniforms[i].name);
free(sha->uniforms);
if(((Shader *)sha)->uniforms)
free(((Shader *)sha)->uniforms);
delete_element(shas, sha);
free(sha);
return NULL;
}
void delete_shaders(void) {
delete_all_elements((void **)&resources.shaders, delete_shader);
resources_delete_and_unset_all(resources.shaders, delete_shader, NULL);
}

View file

@ -25,22 +25,17 @@ typedef struct Uniform {
struct Shader;
typedef struct Shader {
struct Shader *next;
struct Shader *prev;
char *name;
GLuint prog;
int unicount;
Uniform *uniforms;
} Shader;
void load_shader_snippets(char *filename, char *prefix);
void load_shader_file(char *filename);
void load_shader(char *vheader, char *fheader, char *vtext, char *ftext, char *name, int nsize);
void load_shader_snippets(const char *filename, const char *prefix);
void load_shader_file(const char *filename);
void load_shader(const char *vheader, const char *fheader, const char *vtext, const char *ftext, const char *name, int nsize);
Shader *get_shader(const char *name);
void delete_shaders(void);
void cache_uniforms(Shader *sha);
int uniloc(Shader *sha, char *name);
int uniloc(Shader *sha, const char *name);
#endif

View file

@ -6,21 +6,17 @@
*/
#include <png.h>
#include <assert.h>
#include "texture.h"
#include "resource.h"
#include "global.h"
#include "paths/native.h"
#include "taisei_err.h"
#include "list.h"
#include "vbo.h"
Texture *get_tex(char *name) {
Texture *t, *res = NULL;
for(t = resources.textures; t; t = t->next) {
if(strcmp(t->name, name) == 0)
res = t;
}
Texture *get_tex(const char *name) {
Texture *res = hashtable_get_string(resources.textures, name);
if(res == NULL)
errx(-1,"get_tex():\n!- cannot load texture '%s'", name);
@ -28,43 +24,44 @@ Texture *get_tex(char *name) {
return res;
}
Texture *prefix_get_tex(char *name, char *prefix) {
char *src;
Texture *prefix_get_tex(const char *name, const char *prefix) {
const char *src;
if((src = strrchr(name, '/')))
src++;
else
src = name;
char *buf = malloc(strlen(src) + strlen(prefix) + 1);
char buf[strlen(src) + strlen(prefix) + 1];
strcpy(buf, prefix);
strcat(buf, src);
Texture *tex = get_tex(buf);
free(buf);
return tex;
return get_tex(buf);
}
void delete_texture(void **texs, void *tex) {
Texture *t = (Texture *)tex;
free(t->name);
glDeleteTextures(1, &t->gltex);
delete_element((void **)texs, tex);
static void* delete_texture(void *name, void *tex, void *arg) {
free_texture((Texture*)tex);
return NULL;
}
void delete_textures(void) {
delete_all_elements((void **)&resources.textures, delete_texture);
resources_delete_and_unset_all(resources.textures, delete_texture, NULL);
}
Texture *load_texture(const char *filename) {
Texture *texture = hashtable_get_string(resources.textures, filename);
// FIXME: this is for the loading screen
if(texture) {
return texture;
}
SDL_Surface *surface = load_png(filename);
if(surface == NULL)
errx(-1,"load_texture():\n!- cannot load '%s'", filename);
Texture *texture = create_element((void **)&resources.textures, sizeof(Texture));
texture = malloc(sizeof(Texture));
load_sdl_surf(surface, texture);
free(surface->pixels);
SDL_FreeSurface(surface);
@ -73,10 +70,12 @@ Texture *load_texture(const char *filename) {
char *end = strrchr(filename, '.');
int sz = end - beg + 1;
texture->name = malloc(sz);
strlcpy(texture->name, beg, sz);
char name[sz];
strlcpy(name, beg, sz);
printf("-- loaded '%s' as '%s'\n", filename, texture->name);
hashtable_set_string(resources.textures, name, (void*)texture);
printf("-- loaded '%s' as '%s'\n", filename, name);
return texture;
}
@ -188,7 +187,7 @@ void free_texture(Texture *tex) {
free(tex);
}
void draw_texture(float x, float y, char *name) {
void draw_texture(float x, float y, const char *name) {
draw_texture_p(x, y, get_tex(name));
}
@ -222,7 +221,7 @@ void draw_texture_p(float x, float y, Texture *tex) {
glDisable(GL_TEXTURE_2D);
}
void fill_screen(float xoff, float yoff, float ratio, char *name) {
void fill_screen(float xoff, float yoff, float ratio, const char *name) {
fill_screen_p(xoff, yoff, ratio, get_tex(name));
}

View file

@ -15,32 +15,27 @@
typedef struct Texture Texture;
struct Texture {
Texture *next;
Texture *prev;
int w, h;
int truew, trueh;
char *name;
GLuint gltex;
};
Texture *get_tex(char *name);
Texture *prefix_get_tex(char *name, char *prefix);
Texture *get_tex(const char *name);
Texture *prefix_get_tex(const char *name, const char *prefix);
SDL_Surface *load_png(const char *filename);
void delete_texture(void **texs, void *tex);
void delete_textures(void);
Texture *load_texture(const char *filename);
void load_sdl_surf(SDL_Surface *surface, Texture *texture);
void free_texture(Texture *tex);
void draw_texture(float x, float y, char *name);
void draw_texture(float x, float y, const char *name);
void draw_texture_p(float x, float y, Texture *tex);
void fill_screen(float xoff, float yoff, float ratio, char *name);
void fill_screen(float xoff, float yoff, float ratio, const char *name);
void fill_screen_p(float xoff, float yoff, float ratio, Texture *tex);
#endif