You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
2.0 KiB
107 lines
2.0 KiB
2 years ago
|
#define _POSIX_C_SOURCE 200809l
|
||
|
#define _GNU_SOURCE
|
||
|
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <stdint.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "hash.h"
|
||
|
#include "font.h"
|
||
|
#include "util.h"
|
||
|
|
||
|
|
||
|
static struct hm_ref *hash_table;
|
||
|
static struct font_glyph 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;
|
||
|
|
||
|
|
||
|
static inline void set_bit(unsigned int x)
|
||
|
{
|
||
|
// printf("cycles: %d, set: %d\n", cycles, x);
|
||
|
cycles = (cycles+1)%NCYCLES;
|
||
|
if (!cycles) B_RESET();
|
||
|
B_SET(x);
|
||
|
}
|
||
|
|
||
|
|
||
|
void cache_init(void)
|
||
|
{
|
||
|
hash_table = hm_create(CACHE_SIZE);
|
||
|
}
|
||
|
|
||
|
|
||
|
void cache_destroy(void)
|
||
|
{
|
||
|
hm_destroy(hash_table);
|
||
|
}
|
||
|
|
||
|
|
||
|
struct font_glyph * cache_get(unsigned int code)
|
||
|
{
|
||
|
struct hm_entry *r = hm_search(hash_table, code);
|
||
|
|
||
|
// miss
|
||
|
if (!r)
|
||
|
return NULL;
|
||
|
|
||
|
// hit
|
||
|
set_bit((struct font_glyph *)(r->data)-cache_array);
|
||
|
return (struct font_glyph *)(r->data);
|
||
|
}
|
||
|
|
||
|
|
||
|
int cache_insert(struct font_glyph *g)
|
||
|
{
|
||
|
struct font_glyph *spot = NULL;
|
||
|
uint32_t x = 0;
|
||
|
// find an open spot in the cache
|
||
|
// TODO: use __builtin_clz to speed this up
|
||
|
for (; x < CACHE_SIZE; x++) {
|
||
|
// printf("test: %d\n", x);
|
||
|
if (!B_TEST(x))
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// allocation in cache failed
|
||
|
if (B_TEST(x))
|
||
|
return -1;
|
||
|
|
||
|
set_bit(x);
|
||
|
spot = &cache_array[x];
|
||
|
*spot = *g;
|
||
|
|
||
|
/*
|
||
|
for (int i = 0; i < _BSIZE; i++) {
|
||
|
//print_byte(bitmap[i]);
|
||
|
//print_byte(bitmap[i]>>8);
|
||
|
//print_byte(bitmap[i]>>16);
|
||
|
//print_byte(bitmap[i]>>24);
|
||
|
//print_byte(bitmap[i]>>32);
|
||
|
//print_byte(bitmap[i]>>40);
|
||
|
//print_byte(bitmap[i]>>48);
|
||
|
//print_byte(bitmap[i]>>56);
|
||
|
printf("%lx", bitmap[i]);
|
||
|
}
|
||
|
printf("\n");
|
||
|
*/
|
||
|
|
||
|
struct hm_entry e = { .code = g->codepoint, .data = spot};
|
||
|
if (!hm_insert(hash_table, &e))
|
||
|
return -1;
|
||
|
|
||
|
return 0;
|
||
|
}
|