cache of img for layouts

This commit is contained in:
p.kosyh 2010-01-23 06:21:53 +00:00
parent 31c6a11a9e
commit b59609e178
7 changed files with 370 additions and 11 deletions

View file

@ -5,7 +5,7 @@ CFLAGS += $(SDL_CFLAGS) $(LUA_CFLAGS) -DLANG_PATH=\"${LANGPATH}/\" -DSTEAD_PATH=
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))

154
src/sdl-instead/cache.c Normal file
View 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
View 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

View file

@ -1290,6 +1290,7 @@ struct layout {
int saved_align;
int style;
int lstyle;
cache_t img_cache;
};
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->acol = gfx_col(255, 0, 0);
l->box = NULL;
l->img_cache = cache_init(GFX_CACHE_SIZE, gfx_free_image);
return l;
}
void txt_layout_size(layout_t lay, int *w, int *h)
@ -1499,6 +1501,9 @@ void _txt_layout_free(layout_t lay)
while (g) {
struct image *og = g;
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);
}
layout->images = NULL;
@ -1508,7 +1513,10 @@ void _txt_layout_free(layout_t lay)
void txt_layout_free(layout_t lay)
{
struct layout *layout = (struct layout *)lay;
_txt_layout_free(lay);
cache_free(layout->img_cache);
layout->img_cache = NULL;
free(lay);
}
@ -2212,6 +2220,7 @@ img_t get_img(struct layout *layout, char *p)
{
int len;
img_t img;
struct image *image;
len = word_img(p, NULL);
if (!len)
return NULL;
@ -2219,18 +2228,25 @@ img_t get_img(struct layout *layout, char *p)
p[len - 1] = 0;
img = layout_lookup_image(layout, p);
if (!img && (img = gfx_load_image(p))) {
struct image *image;
if (img)
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 :( */
image = image_new(p, img);
if (!image) {
gfx_free_image(img);
img = NULL;
} else {
layout_add_image(layout, image);
image->free_it = 1; /* free on layout destroy */
}
}
image = image_new(p, img);
if (!image) {
gfx_free_image(img);
img = NULL;
} else {
layout_add_image(layout, image);
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] = '>';
return img;
}

View file

@ -1,5 +1,10 @@
#ifndef __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* img_t;
typedef void* fnt_t;

View file

@ -1,3 +1,4 @@
#include "cache.h"
#include "graphics.h"
#include "sound.h"
#include "game.h"

168
src/sdl-instead/list.h Normal file
View 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