cache of img for layouts
This commit is contained in:
parent
31c6a11a9e
commit
b59609e178
|
@ -5,7 +5,7 @@ CFLAGS += $(SDL_CFLAGS) $(LUA_CFLAGS) -DLANG_PATH=\"${LANGPATH}/\" -DSTEAD_PATH=
|
||||||
|
|
||||||
LDFLAGS += $(SDL_LFLAGS) $(LUA_LFLAGS)
|
LDFLAGS += $(SDL_LFLAGS) $(LUA_LFLAGS)
|
||||||
|
|
||||||
SRC := graphics.c input.c game.c main.c instead.c sound.c SDL_rotozoom.c SDL_anigif.c SDL_gfxBlitFunc.c config.c themes.c menu.c util.c $(PLATFORM)
|
SRC := graphics.c input.c game.c main.c instead.c sound.c SDL_rotozoom.c SDL_anigif.c SDL_gfxBlitFunc.c config.c themes.c menu.c util.c cache.c $(PLATFORM)
|
||||||
|
|
||||||
OBJ := $(patsubst %.c, %.o, $(SRC))
|
OBJ := $(patsubst %.c, %.o, $(SRC))
|
||||||
|
|
||||||
|
|
154
src/sdl-instead/cache.c
Normal file
154
src/sdl-instead/cache.c
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "list.h"
|
||||||
|
#include "cache.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct list_head list;
|
||||||
|
int size;
|
||||||
|
int max_size;
|
||||||
|
cache_free_fn free_fn;
|
||||||
|
} __cache_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
struct list_head list;
|
||||||
|
char *name;
|
||||||
|
void *data;
|
||||||
|
int free_it;
|
||||||
|
} __cache_e_t;
|
||||||
|
|
||||||
|
cache_t cache_init(int size, cache_free_fn free_fn)
|
||||||
|
{
|
||||||
|
__cache_t *c = malloc(sizeof(__cache_t));
|
||||||
|
if (!c)
|
||||||
|
return NULL;
|
||||||
|
INIT_LIST_HEAD(&c->list);
|
||||||
|
c->size = 0;
|
||||||
|
c->max_size = size;
|
||||||
|
c->free_fn = free_fn;
|
||||||
|
return (cache_t)c;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cache_e_free(cache_t cache, __cache_e_t *cc)
|
||||||
|
{
|
||||||
|
__cache_t *c = cache;
|
||||||
|
if (!c)
|
||||||
|
return;
|
||||||
|
free(cc->name);
|
||||||
|
if (c->free_fn && cc->free_it)
|
||||||
|
c->free_fn(cc->data);
|
||||||
|
list_del((struct list_head*)cc);
|
||||||
|
free(cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cache_zap(cache_t cache)
|
||||||
|
{
|
||||||
|
__cache_t *c = cache;
|
||||||
|
if (!c)
|
||||||
|
return;
|
||||||
|
while (!list_empty(&c->list))
|
||||||
|
cache_e_free(cache, (__cache_e_t *)(c->list.next));
|
||||||
|
c->size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cache_free(cache_t cache)
|
||||||
|
{
|
||||||
|
if (!cache)
|
||||||
|
return;
|
||||||
|
cache_zap(cache);
|
||||||
|
free(cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __cache_e_t *cache_lookup(cache_t cache, const char *name)
|
||||||
|
{
|
||||||
|
struct list_head *pos;
|
||||||
|
__cache_t *c = cache;
|
||||||
|
__cache_e_t *cc;
|
||||||
|
if (!c || !name)
|
||||||
|
return NULL;
|
||||||
|
list_for_each(pos, &c->list) {
|
||||||
|
cc = (__cache_e_t*) pos;
|
||||||
|
if (!strcmp(cc->name, name))
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static __cache_e_t *cache_data(cache_t cache, void *p)
|
||||||
|
{
|
||||||
|
struct list_head *pos;
|
||||||
|
__cache_t *c = cache;
|
||||||
|
__cache_e_t *cc;
|
||||||
|
if (!c || !p)
|
||||||
|
return NULL;
|
||||||
|
list_for_each(pos, &c->list) {
|
||||||
|
cc = (__cache_e_t*) pos;
|
||||||
|
if (p == cc->data)
|
||||||
|
return cc;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cache_forget(cache_t cache, void *p)
|
||||||
|
{
|
||||||
|
__cache_e_t *cc = cache_data(cache, p);
|
||||||
|
if (cc)
|
||||||
|
cc->free_it = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *cache_get(cache_t cache, const char *name)
|
||||||
|
{
|
||||||
|
__cache_e_t *cc;
|
||||||
|
__cache_t *c = cache;
|
||||||
|
if (!c || !name)
|
||||||
|
return NULL;
|
||||||
|
cc = cache_lookup(cache, name);
|
||||||
|
if (!cc)
|
||||||
|
return NULL;
|
||||||
|
cc->free_it = 0; /* need again! */
|
||||||
|
list_move((struct list_head*)cc, &c->list); /* first place */
|
||||||
|
// printf("%p\n", cc->data);
|
||||||
|
return cc->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cache_have(cache_t cache, void *p)
|
||||||
|
{
|
||||||
|
__cache_e_t *cc;
|
||||||
|
__cache_t *c = cache;
|
||||||
|
if (!c || !p)
|
||||||
|
return -1;
|
||||||
|
cc = cache_data(cache, p);
|
||||||
|
if (!cc)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cache_add(cache_t cache, const char *name, void *p)
|
||||||
|
{
|
||||||
|
__cache_e_t *cc;
|
||||||
|
__cache_t *c = cache;
|
||||||
|
if (!c || !name)
|
||||||
|
return -1;
|
||||||
|
cc = cache_lookup(cache, name);
|
||||||
|
if (cc)
|
||||||
|
return 0;
|
||||||
|
cc = malloc(sizeof(__cache_e_t));
|
||||||
|
if (!cc)
|
||||||
|
return -1;
|
||||||
|
cc->name = strdup(name);
|
||||||
|
if (!cc->name) {
|
||||||
|
free(cc);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
cc->data = p;
|
||||||
|
cc->free_it = 0;
|
||||||
|
list_add((struct list_head*)cc, &c->list);
|
||||||
|
c->size ++;
|
||||||
|
// printf("size: %d:%s\n", c->size, name);
|
||||||
|
if (c->size > c->max_size) {
|
||||||
|
c->size --;
|
||||||
|
cache_e_free(cache, (__cache_e_t *)c->list.prev);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
15
src/sdl-instead/cache.h
Normal file
15
src/sdl-instead/cache.h
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef __CACHE_H
|
||||||
|
#define __CACHE_H
|
||||||
|
|
||||||
|
typedef void * cache_t;
|
||||||
|
typedef void (*cache_free_fn)(void *p);
|
||||||
|
|
||||||
|
extern cache_t cache_init(int size, cache_free_fn);
|
||||||
|
extern void cache_free(cache_t cache);
|
||||||
|
extern void cache_forget(cache_t cache, void *p);
|
||||||
|
extern void cache_zap(cache_t cache);
|
||||||
|
extern void *cache_get(cache_t cache, const char *name);
|
||||||
|
extern int cache_add(cache_t cache, const char *name, void *p);
|
||||||
|
extern int cache_have(cache_t cache, void *p);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1290,6 +1290,7 @@ struct layout {
|
||||||
int saved_align;
|
int saved_align;
|
||||||
int style;
|
int style;
|
||||||
int lstyle;
|
int lstyle;
|
||||||
|
cache_t img_cache;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct word_list {
|
struct word_list {
|
||||||
|
@ -1448,6 +1449,7 @@ struct layout *layout_new(fnt_t fn, int w, int h)
|
||||||
l->lcol = gfx_col(0, 0, 255);
|
l->lcol = gfx_col(0, 0, 255);
|
||||||
l->acol = gfx_col(255, 0, 0);
|
l->acol = gfx_col(255, 0, 0);
|
||||||
l->box = NULL;
|
l->box = NULL;
|
||||||
|
l->img_cache = cache_init(GFX_CACHE_SIZE, gfx_free_image);
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
void txt_layout_size(layout_t lay, int *w, int *h)
|
void txt_layout_size(layout_t lay, int *w, int *h)
|
||||||
|
@ -1499,6 +1501,9 @@ void _txt_layout_free(layout_t lay)
|
||||||
while (g) {
|
while (g) {
|
||||||
struct image *og = g;
|
struct image *og = g;
|
||||||
g = g->next;
|
g = g->next;
|
||||||
|
if (!cache_have(layout->img_cache, og->image))
|
||||||
|
og->free_it = 0; /* do not free from cache */
|
||||||
|
cache_forget(layout->img_cache, og->image);
|
||||||
image_free(og);
|
image_free(og);
|
||||||
}
|
}
|
||||||
layout->images = NULL;
|
layout->images = NULL;
|
||||||
|
@ -1508,7 +1513,10 @@ void _txt_layout_free(layout_t lay)
|
||||||
|
|
||||||
void txt_layout_free(layout_t lay)
|
void txt_layout_free(layout_t lay)
|
||||||
{
|
{
|
||||||
|
struct layout *layout = (struct layout *)lay;
|
||||||
_txt_layout_free(lay);
|
_txt_layout_free(lay);
|
||||||
|
cache_free(layout->img_cache);
|
||||||
|
layout->img_cache = NULL;
|
||||||
free(lay);
|
free(lay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2212,6 +2220,7 @@ img_t get_img(struct layout *layout, char *p)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
img_t img;
|
img_t img;
|
||||||
|
struct image *image;
|
||||||
len = word_img(p, NULL);
|
len = word_img(p, NULL);
|
||||||
if (!len)
|
if (!len)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -2219,9 +2228,14 @@ img_t get_img(struct layout *layout, char *p)
|
||||||
p[len - 1] = 0;
|
p[len - 1] = 0;
|
||||||
|
|
||||||
img = layout_lookup_image(layout, p);
|
img = layout_lookup_image(layout, p);
|
||||||
if (!img && (img = gfx_load_image(p))) {
|
if (img)
|
||||||
struct image *image;
|
goto out;
|
||||||
|
img = cache_get(layout->img_cache, p);
|
||||||
|
if (!img) {
|
||||||
|
if (!(img = gfx_load_image(p)))
|
||||||
|
return NULL;
|
||||||
theme_img_scale(&img); /* bad style, no gfx layer :( */
|
theme_img_scale(&img); /* bad style, no gfx layer :( */
|
||||||
|
}
|
||||||
image = image_new(p, img);
|
image = image_new(p, img);
|
||||||
if (!image) {
|
if (!image) {
|
||||||
gfx_free_image(img);
|
gfx_free_image(img);
|
||||||
|
@ -2229,8 +2243,10 @@ img_t get_img(struct layout *layout, char *p)
|
||||||
} else {
|
} else {
|
||||||
layout_add_image(layout, image);
|
layout_add_image(layout, image);
|
||||||
image->free_it = 1; /* free on layout destroy */
|
image->free_it = 1; /* free on layout destroy */
|
||||||
|
if (gfx_img_w(img) <= GFX_MAX_CACHED_W && gfx_img_h(img) <= GFX_MAX_CACHED_H)
|
||||||
|
cache_add(layout->img_cache, p, img);
|
||||||
}
|
}
|
||||||
}
|
out:
|
||||||
p[len - 1] = '>';
|
p[len - 1] = '>';
|
||||||
return img;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
#ifndef __GRAPHICS_H__
|
#ifndef __GRAPHICS_H__
|
||||||
#define __GRAPHICS_H__
|
#define __GRAPHICS_H__
|
||||||
|
|
||||||
|
#define GFX_CACHE_SIZE 32
|
||||||
|
#define GFX_MAX_CACHED_W 256
|
||||||
|
#define GFX_MAX_CACHED_H 256
|
||||||
|
|
||||||
typedef void* gtimer_t;
|
typedef void* gtimer_t;
|
||||||
typedef void* img_t;
|
typedef void* img_t;
|
||||||
typedef void* fnt_t;
|
typedef void* fnt_t;
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "cache.h"
|
||||||
#include "graphics.h"
|
#include "graphics.h"
|
||||||
#include "sound.h"
|
#include "sound.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
|
168
src/sdl-instead/list.h
Normal file
168
src/sdl-instead/list.h
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
#ifndef _LIST_H
|
||||||
|
#define _LIST_H
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define LIST_POISON1 NULL
|
||||||
|
#define LIST_POISON2 NULL
|
||||||
|
|
||||||
|
struct list_head {
|
||||||
|
struct list_head *next, *prev;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LIST_HEAD_INIT(name) { &(name), &(name) }
|
||||||
|
|
||||||
|
#define LIST_HEAD(name) \
|
||||||
|
struct list_head name = LIST_HEAD_INIT(name)
|
||||||
|
|
||||||
|
static inline void INIT_LIST_HEAD(struct list_head *list)
|
||||||
|
{
|
||||||
|
list->next = list;
|
||||||
|
list->prev = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __list_add(struct list_head *new,
|
||||||
|
struct list_head *prev,
|
||||||
|
struct list_head *next)
|
||||||
|
{
|
||||||
|
next->prev = new;
|
||||||
|
new->next = next;
|
||||||
|
new->prev = prev;
|
||||||
|
prev->next = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_add(struct list_head *new, struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_add(new, head, head->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_add_tail(struct list_head *new, struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_add(new, head->prev, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __list_del(struct list_head * prev, struct list_head * next)
|
||||||
|
{
|
||||||
|
next->prev = prev;
|
||||||
|
prev->next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_del(struct list_head *entry)
|
||||||
|
{
|
||||||
|
__list_del(entry->prev, entry->next);
|
||||||
|
entry->next = LIST_POISON1;
|
||||||
|
entry->prev = LIST_POISON2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_replace(struct list_head *old,
|
||||||
|
struct list_head *new)
|
||||||
|
{
|
||||||
|
new->next = old->next;
|
||||||
|
new->next->prev = new;
|
||||||
|
new->prev = old->prev;
|
||||||
|
new->prev->next = new;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_replace_init(struct list_head *old,
|
||||||
|
struct list_head *new)
|
||||||
|
{
|
||||||
|
list_replace(old, new);
|
||||||
|
INIT_LIST_HEAD(old);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_del_init(struct list_head *entry)
|
||||||
|
{
|
||||||
|
__list_del(entry->prev, entry->next);
|
||||||
|
INIT_LIST_HEAD(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_move(struct list_head *list, struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_del(list->prev, list->next);
|
||||||
|
list_add(list, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_move_tail(struct list_head *list,
|
||||||
|
struct list_head *head)
|
||||||
|
{
|
||||||
|
__list_del(list->prev, list->next);
|
||||||
|
list_add_tail(list, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int list_is_last(const struct list_head *list,
|
||||||
|
const struct list_head *head)
|
||||||
|
{
|
||||||
|
return list->next == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int list_empty(const struct list_head *head)
|
||||||
|
{
|
||||||
|
return head->next == head;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void __list_splice(const struct list_head *list,
|
||||||
|
struct list_head *prev,
|
||||||
|
struct list_head *next)
|
||||||
|
{
|
||||||
|
struct list_head *first = list->next;
|
||||||
|
struct list_head *last = list->prev;
|
||||||
|
|
||||||
|
first->prev = prev;
|
||||||
|
prev->next = first;
|
||||||
|
|
||||||
|
last->next = next;
|
||||||
|
next->prev = last;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_splice(const struct list_head *list,
|
||||||
|
struct list_head *head)
|
||||||
|
{
|
||||||
|
if (!list_empty(list))
|
||||||
|
__list_splice(list, head, head->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_splice_tail(struct list_head *list,
|
||||||
|
struct list_head *head)
|
||||||
|
{
|
||||||
|
if (!list_empty(list))
|
||||||
|
__list_splice(list, head->prev, head);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_splice_init(struct list_head *list,
|
||||||
|
struct list_head *head)
|
||||||
|
{
|
||||||
|
if (!list_empty(list)) {
|
||||||
|
__list_splice(list, head, head->next);
|
||||||
|
INIT_LIST_HEAD(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void list_splice_tail_init(struct list_head *list,
|
||||||
|
struct list_head *head)
|
||||||
|
{
|
||||||
|
if (!list_empty(list)) {
|
||||||
|
__list_splice(list, head->prev, head);
|
||||||
|
INIT_LIST_HEAD(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define list_for_each(pos, head) \
|
||||||
|
for (pos = (head)->next; pos != (head); \
|
||||||
|
pos = pos->next)
|
||||||
|
|
||||||
|
#define __list_for_each(pos, head) \
|
||||||
|
for (pos = (head)->next; pos != (head); pos = pos->next)
|
||||||
|
|
||||||
|
#define list_for_each_prev(pos, head) \
|
||||||
|
for (pos = (head)->prev; pos != (head); \
|
||||||
|
pos = pos->prev)
|
||||||
|
|
||||||
|
#define list_for_each_entry(pos, head, member) \
|
||||||
|
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||||
|
|
||||||
|
#define list_for_each_entry_from(pos, head, member) \
|
||||||
|
for (; &pos->member != (head); \
|
||||||
|
pos = list_entry(pos->member.next, typeof(*pos), member))
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue