forked from len0rd/rockbox
move the statically allocated tokens array into the skin buffer. this is done with a little bit of magic with the buffer... explanation in the comments but breifly, tokens + images are stored at the front of the buffer, everything else (constant sizes) are stored at the back, the 2 ends meet when the buffer is full.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22418 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
2492e258fa
commit
98756fe492
4 changed files with 104 additions and 22 deletions
|
|
@ -38,6 +38,15 @@
|
||||||
* MAIN_ and REMOTE_BUFFER are just for reasonable size calibration,
|
* MAIN_ and REMOTE_BUFFER are just for reasonable size calibration,
|
||||||
* both screens can use the whole buffer as they need; it's not split
|
* both screens can use the whole buffer as they need; it's not split
|
||||||
* between screens
|
* between screens
|
||||||
|
*
|
||||||
|
* Buffer can be allocated from either "end" of the global buffer.
|
||||||
|
* items with unknown sizes get allocated from the start (0->) (data)
|
||||||
|
* items with known sizes get allocated from the end (<-buf_size) (tokens)
|
||||||
|
* After loading 2 skins the buffer will look like this:
|
||||||
|
* |tokens skin1|images skin2|---SPACE---|data skin2|data skin1|
|
||||||
|
* Make sure to never start allocating from the beginning before letting us know
|
||||||
|
* how much was used. and RESPECT THE buf_free RETURN VALUES!
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -55,63 +64,93 @@
|
||||||
#define SKIN_BUFFER_SIZE (MAIN_BUFFER + REMOTE_BUFFER)
|
#define SKIN_BUFFER_SIZE (MAIN_BUFFER + REMOTE_BUFFER)
|
||||||
|
|
||||||
|
|
||||||
static unsigned char buffer_start[SKIN_BUFFER_SIZE], *buffer_pos = NULL;
|
static unsigned char buffer[SKIN_BUFFER_SIZE];
|
||||||
|
static unsigned char *buffer_front = NULL; /* start of the free space,
|
||||||
|
increases with allocation*/
|
||||||
|
static unsigned char *buffer_back = NULL; /* end of the free space
|
||||||
|
decreases with allocation */
|
||||||
static size_t buf_size = SKIN_BUFFER_SIZE;
|
static size_t buf_size = SKIN_BUFFER_SIZE;
|
||||||
|
|
||||||
void skin_buffer_init(void)
|
void skin_buffer_init(void)
|
||||||
{
|
{
|
||||||
#if 0 /* this will go in again later probably */
|
#if 0 /* this will go in again later probably */
|
||||||
if (buffer_start == NULL)
|
if (buffer == NULL)
|
||||||
{
|
{
|
||||||
buf_size = SKIN_BUFFER_SIZE;/* global_settings.skin_buf_size */
|
buf_size = SKIN_BUFFER_SIZE;/* global_settings.skin_buf_size */
|
||||||
|
|
||||||
buffer_start = buffer_alloc(buf_size);
|
buffer = buffer_alloc(buf_size);
|
||||||
buffer_pos = buffer_start;
|
buffer_front = buffer;
|
||||||
|
buffer_back = bufer + buf_size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* reset the buffer.... */
|
/* reset the buffer.... */
|
||||||
buffer_pos = buffer_start;
|
buffer_front = buffer;
|
||||||
|
buffer_back = buffer + buf_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the number of bytes currently being used */
|
/* get the number of bytes currently being used */
|
||||||
size_t skin_buffer_usage(void)
|
size_t skin_buffer_usage(void)
|
||||||
{
|
{
|
||||||
return buffer_pos-buffer_start;
|
return buf_size - (buffer_back-buffer_front);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate size bytes from the buffer */
|
size_t skin_buffer_freespace(void)
|
||||||
|
{
|
||||||
|
return buffer_back-buffer_front;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate size bytes from the buffer
|
||||||
|
* allocates from the back end (data end)
|
||||||
|
*/
|
||||||
void* skin_buffer_alloc(size_t size)
|
void* skin_buffer_alloc(size_t size)
|
||||||
{
|
{
|
||||||
void* retval = buffer_pos;
|
if (skin_buffer_freespace() <= size)
|
||||||
if (skin_buffer_usage()+size >= buf_size)
|
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
buffer_pos += size;
|
buffer_back -= size;
|
||||||
/* 32-bit aligned */
|
/* 32-bit aligned */
|
||||||
buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3);
|
buffer_back = (void *)(((unsigned long)buffer_back) & ~3);
|
||||||
return retval;
|
return buffer_back;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a pointer to the skin buffer and the count of how much is free
|
/* Get a pointer to the skin buffer and the count of how much is free
|
||||||
* used to do your own buffer management.
|
* used to do your own buffer management.
|
||||||
* Any memory used will be overwritten next time wps_buffer_alloc()
|
* Any memory used will be overwritten next time wps_buffer_alloc()
|
||||||
* is called unless skin_buffer_increment() is called first
|
* is called unless skin_buffer_increment() is called first
|
||||||
|
*
|
||||||
|
* This is from the start of the buffer, it is YOUR responsility to make
|
||||||
|
* sure you dont ever use more then *freespace, and bear in mind this will only
|
||||||
|
* be valid untill skin_buffer_alloc() is next called...
|
||||||
|
* so call skin_buffer_increment() and skin_buffer_freespace() regularly
|
||||||
*/
|
*/
|
||||||
void* skin_buffer_grab(size_t *freespace)
|
void* skin_buffer_grab(size_t *freespace)
|
||||||
{
|
{
|
||||||
*freespace = buf_size - skin_buffer_usage();
|
*freespace = buf_size - skin_buffer_usage();
|
||||||
return buffer_pos;
|
return buffer_front;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Use after skin_buffer_grab() to specify how much buffer was used */
|
/* Use after skin_buffer_grab() to specify how much buffer was used */
|
||||||
void skin_buffer_increment(size_t used)
|
void skin_buffer_increment(size_t used, bool align)
|
||||||
{
|
{
|
||||||
buffer_pos += used;
|
buffer_front += used;
|
||||||
/* 32-bit aligned */
|
if (align)
|
||||||
buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3);
|
{
|
||||||
|
/* 32-bit aligned */
|
||||||
|
buffer_front = (void *)(((unsigned long)buffer_front + 3) & ~3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* free previously skin_buffer_increment()'ed space. This just moves the pointer
|
||||||
|
* back 'used' bytes so make sure you actually want to do this */
|
||||||
|
void skin_buffer_free_from_front(size_t used)
|
||||||
|
{
|
||||||
|
buffer_front -= used;
|
||||||
|
/* 32-bit aligned */
|
||||||
|
buffer_front = (void *)(((unsigned long)buffer_front + 3) & ~3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ void skin_buffer_init(void);
|
||||||
|
|
||||||
/* get the number of bytes currently being used */
|
/* get the number of bytes currently being used */
|
||||||
size_t skin_buffer_usage(void);
|
size_t skin_buffer_usage(void);
|
||||||
|
size_t skin_buffer_freespace(void);
|
||||||
|
|
||||||
/* Allocate size bytes from the buffer */
|
/* Allocate size bytes from the buffer */
|
||||||
void* skin_buffer_alloc(size_t size);
|
void* skin_buffer_alloc(size_t size);
|
||||||
|
|
@ -42,10 +43,22 @@ void* skin_buffer_alloc(size_t size);
|
||||||
* used to do your own buffer management.
|
* used to do your own buffer management.
|
||||||
* Any memory used will be overwritten next time wps_buffer_alloc()
|
* Any memory used will be overwritten next time wps_buffer_alloc()
|
||||||
* is called unless skin_buffer_increment() is called first
|
* is called unless skin_buffer_increment() is called first
|
||||||
|
*
|
||||||
|
* This is from the start of the buffer, it is YOUR responsility to make
|
||||||
|
* sure you dont ever use more then *freespace, and bear in mind this will only
|
||||||
|
* be valid untill skin_buffer_alloc() is next called...
|
||||||
|
* so call skin_buffer_increment() and skin_buffer_freespace() regularly
|
||||||
*/
|
*/
|
||||||
void* skin_buffer_grab(size_t *freespace);
|
void* skin_buffer_grab(size_t *freespace);
|
||||||
|
|
||||||
/* Use after skin_buffer_grab() to specify how much buffer was used */
|
/* Use after skin_buffer_grab() to specify how much buffer was used.
|
||||||
void skin_buffer_increment(size_t used);
|
* align should always be true unless there is a possibility that you will need
|
||||||
|
* more space *immediatly* after the previous allocation. (i.e in an array).
|
||||||
|
* NEVER leave the buffer unaligned */
|
||||||
|
void skin_buffer_increment(size_t used, bool align);
|
||||||
|
|
||||||
|
/* free previously skin_buffer_increment()'ed space. This just moves the pointer
|
||||||
|
* back 'used' bytes so make sure you actually want to do this */
|
||||||
|
void skin_buffer_free_from_front(size_t used);
|
||||||
|
|
||||||
#endif /* _SKIN_BUFFER_H_ */
|
#endif /* _SKIN_BUFFER_H_ */
|
||||||
|
|
|
||||||
|
|
@ -1274,18 +1274,44 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
|
||||||
data is the pointer to the structure where the parsed WPS should be stored.
|
data is the pointer to the structure where the parsed WPS should be stored.
|
||||||
It is initialised.
|
It is initialised.
|
||||||
wps_bufptr points to the string containing the WPS tags */
|
wps_bufptr points to the string containing the WPS tags */
|
||||||
|
#define TOKEN_BLOCK_SIZE 128
|
||||||
static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
|
static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
|
||||||
{
|
{
|
||||||
if (!data || !wps_bufptr || !*wps_bufptr)
|
if (!data || !wps_bufptr || !*wps_bufptr)
|
||||||
return false;
|
return false;
|
||||||
enum wps_parse_error fail = PARSE_OK;
|
enum wps_parse_error fail = PARSE_OK;
|
||||||
int ret;
|
int ret;
|
||||||
|
int max_tokens = TOKEN_BLOCK_SIZE;
|
||||||
|
size_t buf_free = 0;
|
||||||
line = 1;
|
line = 1;
|
||||||
level = -1;
|
level = -1;
|
||||||
|
|
||||||
while(*wps_bufptr && !fail && data->num_tokens < WPS_MAX_TOKENS - 1
|
/* allocate enough RAM for a reasonable skin, grow as needed.
|
||||||
|
* Free any used RAM before loading the images to be 100% RAM efficient */
|
||||||
|
data->tokens = (struct wps_token *)skin_buffer_grab(&buf_free);
|
||||||
|
if (sizeof(struct wps_token)*max_tokens >= buf_free)
|
||||||
|
return false;
|
||||||
|
skin_buffer_increment(max_tokens * sizeof(struct wps_token), false);
|
||||||
|
data->num_tokens = 0;
|
||||||
|
|
||||||
|
while(*wps_bufptr && !fail
|
||||||
&& data->num_lines < WPS_MAX_LINES)
|
&& data->num_lines < WPS_MAX_LINES)
|
||||||
{
|
{
|
||||||
|
/* first make sure there is enough room for tokens */
|
||||||
|
if (max_tokens -1 == data->num_tokens)
|
||||||
|
{
|
||||||
|
int extra_tokens = TOKEN_BLOCK_SIZE;
|
||||||
|
size_t needed = extra_tokens * sizeof(struct wps_token);
|
||||||
|
/* do some smarts here to grow the array a bit */
|
||||||
|
if (skin_buffer_freespace() < needed)
|
||||||
|
{
|
||||||
|
fail = PARSE_FAIL_LIMITS_EXCEEDED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
skin_buffer_increment(needed, false);
|
||||||
|
max_tokens += extra_tokens;
|
||||||
|
}
|
||||||
|
|
||||||
switch(*wps_bufptr++)
|
switch(*wps_bufptr++)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -1482,6 +1508,10 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
|
||||||
/* one of the limits of the while loop was exceeded */
|
/* one of the limits of the while loop was exceeded */
|
||||||
fail = PARSE_FAIL_LIMITS_EXCEEDED;
|
fail = PARSE_FAIL_LIMITS_EXCEEDED;
|
||||||
|
|
||||||
|
/* Success! */
|
||||||
|
/* freeup unused tokens */
|
||||||
|
skin_buffer_free_from_front(sizeof(struct wps_token)
|
||||||
|
* (max_tokens - data->num_tokens));
|
||||||
curr_vp->last_line = data->num_lines - 1;
|
curr_vp->last_line = data->num_lines - 1;
|
||||||
|
|
||||||
#if defined(DEBUG) || defined(SIMULATOR)
|
#if defined(DEBUG) || defined(SIMULATOR)
|
||||||
|
|
@ -1528,7 +1558,7 @@ static bool load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char
|
||||||
|
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
{
|
{
|
||||||
skin_buffer_increment(ret);
|
skin_buffer_increment(ret, true);
|
||||||
loaded = true;
|
loaded = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ struct wps_data
|
||||||
/* Total number of tokens in the WPS. During WPS parsing, this is
|
/* Total number of tokens in the WPS. During WPS parsing, this is
|
||||||
the index of the token being parsed. */
|
the index of the token being parsed. */
|
||||||
int num_tokens;
|
int num_tokens;
|
||||||
struct wps_token tokens[WPS_MAX_TOKENS];
|
struct wps_token *tokens;
|
||||||
|
|
||||||
struct skin_token_list *strings;
|
struct skin_token_list *strings;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue