Merge branch 'master' of http://git.alemauri.eu/alema/ugui
This commit is contained in:
commit
980ea28a5b
73
cache/cache.c
vendored
73
cache/cache.c
vendored
@ -1,73 +0,0 @@
|
|||||||
#define _POSIX_C_SOURCE 200809l
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <search.h>
|
|
||||||
|
|
||||||
#define CACHE_SIZE 512
|
|
||||||
|
|
||||||
static struct hsearch_data hash_table;
|
|
||||||
struct data {
|
|
||||||
unsigned int glyph;
|
|
||||||
unsigned int w, h, u, v;
|
|
||||||
};
|
|
||||||
static struct data cache_array[CACHE_SIZE] = {0};
|
|
||||||
|
|
||||||
// bitmap size is aligned to word
|
|
||||||
#define _BSIZE (CACHE_SIZE+0x3f)&(~0x3f)
|
|
||||||
static uint64_t bitmap[_BSIZE] = {0};
|
|
||||||
|
|
||||||
// bitmap operations
|
|
||||||
#define B_RESET() memset(bitmap, 0, _BSIZE*sizeof(uint64_t))
|
|
||||||
#define B_SET(x) bitmap[(x)/_BSIZE] = 1<<((x)%_BSIZE)
|
|
||||||
#define B_TEST(x) (bitmap[(x)/_BSIZE]&(1<<((x)%_BSIZE)))
|
|
||||||
|
|
||||||
// reset the bitmap every n cycles
|
|
||||||
#define NCYCLES (CACHE_SIZE/2)
|
|
||||||
static int cycles = 0;
|
|
||||||
|
|
||||||
|
|
||||||
void cache_init()
|
|
||||||
{
|
|
||||||
hcreate_r(CACHE_SIZE, &hash_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void cache_destroy()
|
|
||||||
{
|
|
||||||
hdestroy_r(&hash_table);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// d->glyph already contains the right glyph
|
|
||||||
struct data * cache_get(uint32_t glyph)
|
|
||||||
{
|
|
||||||
static char gstr[5] = {0};
|
|
||||||
static ENTRY e, *r;
|
|
||||||
memcpy(gstr, &glyph, 4);
|
|
||||||
e.data = gstr;
|
|
||||||
hsearch_r(e, FIND, &r, &hash_table);
|
|
||||||
|
|
||||||
// miss
|
|
||||||
if (!r)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
// hit
|
|
||||||
cycles = (cycles+1)%NCYCLES;
|
|
||||||
if (!cycles) B_RESET();
|
|
||||||
B_SET((struct data *)(r->data)-cache_array);
|
|
||||||
return (struct data *)(r->data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int cache_insert(struct data *d)
|
|
||||||
{
|
|
||||||
struct data *spot = NULL;
|
|
||||||
uint32_t x = 0;
|
|
||||||
for (; x < CACHE_SIZE; x++)
|
|
||||||
if (!B_TEST(x))
|
|
||||||
break;
|
|
||||||
}
|
|
@ -1,6 +1,8 @@
|
|||||||
CC = gcc
|
CC = gcc
|
||||||
LDFLAGS = -lm -lgrapheme -lSDL2 -lGLEW -lGL
|
# instrumentation flags
|
||||||
CFLAGS = -ggdb3 -Wall -Wextra -pedantic -std=c11 -Wno-unused-function -fno-omit-frame-pointer
|
INFLAGS = -fsanitize=address,builtin,undefined
|
||||||
|
LDFLAGS = -lm -lgrapheme -lSDL2 -lGLEW -lGL ${INFLAGS}
|
||||||
|
CFLAGS = -ggdb3 -Wall -Wextra -pedantic -std=c11 -Wno-unused-function -fno-omit-frame-pointer ${INFLAGS}
|
||||||
|
|
||||||
.PHONY: clean all
|
.PHONY: clean all
|
||||||
all: test
|
all: test
|
||||||
|
@ -151,7 +151,7 @@ const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsig
|
|||||||
|
|
||||||
// TODO: bounds check usign atlas height
|
// TODO: bounds check usign atlas height
|
||||||
// TODO: clear spot area in the atlas before writing on it
|
// TODO: clear spot area in the atlas before writing on it
|
||||||
unsigned int spot = cache_get(&PRIV(atlas)->c);
|
unsigned int spot = cache_get_free_spot(&PRIV(atlas)->c);
|
||||||
unsigned int ty = ((atlas->glyph_max_w * spot) / atlas->width) * atlas->glyph_max_h;
|
unsigned int ty = ((atlas->glyph_max_w * spot) / atlas->width) * atlas->glyph_max_h;
|
||||||
unsigned int tx = (atlas->glyph_max_w * spot) % atlas->width;
|
unsigned int tx = (atlas->glyph_max_w * spot) % atlas->width;
|
||||||
unsigned int w = atlas->width;
|
unsigned int w = atlas->width;
|
||||||
@ -179,7 +179,7 @@ const struct font_glyph * font_get_glyph_texture(struct font_atlas *atlas, unsig
|
|||||||
.y = off_y-base,
|
.y = off_y-base,
|
||||||
.a = adv,
|
.a = adv,
|
||||||
};
|
};
|
||||||
return cache_insert(&PRIV(atlas)->c, &g, g.codepoint, spot);
|
return cache_insert_at(&PRIV(atlas)->c, &g, g.codepoint, spot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
// as the code and not a generic type
|
// as the code and not a generic type
|
||||||
|
|
||||||
|
|
||||||
#define CACHE_USED(c, x) \
|
#define CACHE_CYCLE(c) \
|
||||||
{ \
|
{ \
|
||||||
if (++(c->cycles) > CACHE_NCYCLES) { \
|
if (++(c->cycles) > CACHE_NCYCLES) { \
|
||||||
for (int i = 0; i < CACHE_BSIZE; i++) { \
|
for (int i = 0; i < CACHE_BSIZE; i++) { \
|
||||||
@ -24,7 +24,6 @@
|
|||||||
} \
|
} \
|
||||||
c->cycles = 0; \
|
c->cycles = 0; \
|
||||||
} \
|
} \
|
||||||
CACHE_BSET(c->used, x); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -74,13 +73,14 @@ const type * name##_search(struct name *cache, uint32_t code) \
|
|||||||
if (!CACHE_BTEST(cache->present, r->data)) \
|
if (!CACHE_BTEST(cache->present, r->data)) \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
/* HIT, set as recently used */ \
|
/* HIT, set as recently used */ \
|
||||||
CACHE_USED(cache, r->data); \
|
CACHE_BSET(cache->used, r->data); \
|
||||||
return (&cache->array[r->data]); \
|
return (&cache->array[r->data]); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
/* Look for a free spot in the present bitmap and return its index */ \
|
/* Look for a free spot in the present bitmap and return its index */ \
|
||||||
int name##_get(struct name *cache) \
|
/* If there is no free space left then just return the first position */ \
|
||||||
|
int name##_get_free_spot(struct name *cache) \
|
||||||
{ \
|
{ \
|
||||||
if (!cache) return -1; \
|
if (!cache) return -1; \
|
||||||
int x = 0; \
|
int x = 0; \
|
||||||
@ -95,18 +95,16 @@ int name##_get(struct name *cache) \
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
\
|
\
|
||||||
const type * name##_insert(struct name *cache, const type *g, uint32_t code, int x)\
|
const type * name##_insert_at(struct name *cache, const type *g, uint32_t code, int x)\
|
||||||
{ \
|
{ \
|
||||||
if (!cache) return NULL; \
|
if (!cache) return NULL; \
|
||||||
type *spot = NULL; \
|
type *spot = NULL; \
|
||||||
/* x is the index to the cache array, it has to come from the user */ \
|
/* check if the spot is valid */ \
|
||||||
/* check if the spot is free */ \
|
if (x < 0) return NULL; \
|
||||||
if (x < 0 || CACHE_BTEST(cache->present, x)) \
|
|
||||||
return NULL; \
|
|
||||||
/* Set used and present */ \
|
/* Set used and present */ \
|
||||||
CACHE_USED(cache, x) \
|
|
||||||
CACHE_BSET(cache->present, x); \
|
CACHE_BSET(cache->present, x); \
|
||||||
CACHE_BSET(cache->used, x); \
|
CACHE_BSET(cache->used, x); \
|
||||||
|
CACHE_CYCLE(cache) \
|
||||||
spot = &(cache->array[x]); \
|
spot = &(cache->array[x]); \
|
||||||
*spot = *g; \
|
*spot = *g; \
|
||||||
struct name##table_entry e = { .code = code, .data = x}; \
|
struct name##table_entry e = { .code = code, .data = x}; \
|
||||||
@ -114,6 +112,15 @@ const type * name##_insert(struct name *cache, const type *g, uint32_t code, int
|
|||||||
return NULL; \
|
return NULL; \
|
||||||
return spot; \
|
return spot; \
|
||||||
} \
|
} \
|
||||||
|
\
|
||||||
|
\
|
||||||
|
const type * name##_insert(struct name *cache, const type *g, uint32_t code, int *x)\
|
||||||
|
{ \
|
||||||
|
int y; \
|
||||||
|
if (!x) x = &y; \
|
||||||
|
*x = name##_get_free_spot(cache); \
|
||||||
|
return name##_insert_at(cache, g, code, *x); \
|
||||||
|
} \
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,9 +15,11 @@ rm -f objlist
|
|||||||
|
|
||||||
cat > Makefile << EOF
|
cat > Makefile << EOF
|
||||||
CC = gcc
|
CC = gcc
|
||||||
LDFLAGS = -lm -lgrapheme -lSDL2 -lGLEW -lGL
|
# instrumentation flags
|
||||||
|
INFLAGS = -fsanitize=address,builtin,undefined
|
||||||
|
LDFLAGS = -lm -lgrapheme -lSDL2 -lGLEW -lGL \${INFLAGS}
|
||||||
CFLAGS = -ggdb3 -Wall -Wextra -pedantic -std=c11 \
|
CFLAGS = -ggdb3 -Wall -Wextra -pedantic -std=c11 \
|
||||||
-Wno-unused-function -fno-omit-frame-pointer
|
-Wno-unused-function -fno-omit-frame-pointer \${INFLAGS}
|
||||||
|
|
||||||
.PHONY: clean all
|
.PHONY: clean all
|
||||||
all: test
|
all: test
|
||||||
|
@ -20,25 +20,27 @@ const char *str2 = "The quick brown fox jumps over the lazy dog\n"
|
|||||||
SDL_Window *win;
|
SDL_Window *win;
|
||||||
|
|
||||||
|
|
||||||
|
#define red 0xff0000ff
|
||||||
|
#define blue 0xffff0000
|
||||||
void draw(void)
|
void draw(void)
|
||||||
{
|
{
|
||||||
static unsigned int frame = 0;
|
static unsigned int frame = 0;
|
||||||
printf("frame: %d\n", frame++);
|
printf("frame: %d\n", frame++);
|
||||||
ren_clear();
|
ren_clear();
|
||||||
//ren_render_box(10, 10, 400, 50, 0xffff0000);
|
//ren_render_box(10, 10, 400, 50, blue);
|
||||||
//if (ren_render_text(str1, 10, 10, 400, 50, 20))
|
//if (ren_render_text(str1, 10, 10, 400, 50, 20))
|
||||||
// printf("text: %s\n", ren_strerror());
|
// printf("text: %s\n", ren_strerror());
|
||||||
int w, h;
|
int w, h;
|
||||||
ren_get_text_box(str2, &w, &h, 20);
|
ren_get_text_box(str2, &w, &h, 20);
|
||||||
//printf("box for: %s -> (%d, %d)\n", str2, w, h);
|
//printf("box for: %s -> (%d, %d)\n", str2, w, h);
|
||||||
ren_render_box(0, 0, w, h, 0xffff0000);
|
ren_render_box(0, 0, w, h, blue);
|
||||||
ren_render_text(str2, 0, 0, w, h, 20);
|
ren_render_text(str2, 0, 0, w, h, 20);
|
||||||
|
|
||||||
// fixme: this causes a bug
|
// fixme: this causes a bug
|
||||||
const char *s = "ciao mamma";
|
const char *s = "ciao mamma";
|
||||||
ren_get_text_box(s, &w, &h, 12);
|
ren_get_text_box(s, &w, &h, 12);
|
||||||
s = "stuff that was not in font size 12 -> чащаx";
|
s = "stuff that was not in font size 12 -> чащаx";
|
||||||
ren_render_box(0, 200, w, h, 0xff0000ff);
|
ren_render_box(0, 200, w, h, red);
|
||||||
if (ren_render_text(s, 0, 200, 0xffff, 0xffff, 12))
|
if (ren_render_text(s, 0, 200, 0xffff, 0xffff, 12))
|
||||||
printf("BUG\n");
|
printf("BUG\n");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user