summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorJonathan Gordon <rockbox@jdgordon.info>2009-08-19 04:19:08 +0000
committerJonathan Gordon <rockbox@jdgordon.info>2009-08-19 04:19:08 +0000
commit98756fe4928f25286a2e9aa123cdba4df1163d94 (patch)
treea6591d8d0d148fa482c4379cde000e90b5ed416d /apps
parent2492e258fa9d04ed519c1d58dc69503d18180661 (diff)
downloadrockbox-98756fe4928f25286a2e9aa123cdba4df1163d94.zip
rockbox-98756fe4928f25286a2e9aa123cdba4df1163d94.tar.gz
rockbox-98756fe4928f25286a2e9aa123cdba4df1163d94.tar.bz2
rockbox-98756fe4928f25286a2e9aa123cdba4df1163d94.tar.xz
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
Diffstat (limited to 'apps')
-rw-r--r--apps/gui/skin_engine/skin_buffer.c71
-rw-r--r--apps/gui/skin_engine/skin_buffer.h17
-rw-r--r--apps/gui/skin_engine/skin_parser.c34
-rw-r--r--apps/gui/skin_engine/wps_internals.h2
4 files changed, 103 insertions, 21 deletions
diff --git a/apps/gui/skin_engine/skin_buffer.c b/apps/gui/skin_engine/skin_buffer.c
index 750fec6..70716c1 100644
--- a/apps/gui/skin_engine/skin_buffer.c
+++ b/apps/gui/skin_engine/skin_buffer.c
@@ -38,6 +38,15 @@
* MAIN_ and REMOTE_BUFFER are just for reasonable size calibration,
* both screens can use the whole buffer as they need; it's not split
* 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)
-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;
void skin_buffer_init(void)
{
#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 */
- buffer_start = buffer_alloc(buf_size);
- buffer_pos = buffer_start;
+ buffer = buffer_alloc(buf_size);
+ buffer_front = buffer;
+ buffer_back = bufer + buf_size;
}
else
#endif
{
/* reset the buffer.... */
- buffer_pos = buffer_start;
+ buffer_front = buffer;
+ buffer_back = buffer + buf_size;
}
}
/* get the number of bytes currently being used */
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* retval = buffer_pos;
- if (skin_buffer_usage()+size >= buf_size)
+ if (skin_buffer_freespace() <= size)
{
return NULL;
}
- buffer_pos += size;
+ buffer_back -= size;
/* 32-bit aligned */
- buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3);
- return retval;
+ buffer_back = (void *)(((unsigned long)buffer_back) & ~3);
+ return buffer_back;
}
/* Get a pointer to the skin buffer and the count of how much is free
* used to do your own buffer management.
* Any memory used will be overwritten next time wps_buffer_alloc()
* 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)
{
*freespace = buf_size - skin_buffer_usage();
- return buffer_pos;
+ return buffer_front;
}
/* 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;
+ if (align)
+ {
+ /* 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_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3);
+ buffer_front = (void *)(((unsigned long)buffer_front + 3) & ~3);
}
+
diff --git a/apps/gui/skin_engine/skin_buffer.h b/apps/gui/skin_engine/skin_buffer.h
index 779f575..7d05c95 100644
--- a/apps/gui/skin_engine/skin_buffer.h
+++ b/apps/gui/skin_engine/skin_buffer.h
@@ -33,6 +33,7 @@ void skin_buffer_init(void);
/* get the number of bytes currently being used */
size_t skin_buffer_usage(void);
+size_t skin_buffer_freespace(void);
/* Allocate size bytes from the buffer */
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.
* Any memory used will be overwritten next time wps_buffer_alloc()
* 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);
-/* Use after skin_buffer_grab() to specify how much buffer was used */
-void skin_buffer_increment(size_t used);
+/* Use after skin_buffer_grab() to specify how much buffer was 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_ */
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index b7f2ec3..62ee365 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -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.
It is initialised.
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)
{
if (!data || !wps_bufptr || !*wps_bufptr)
return false;
enum wps_parse_error fail = PARSE_OK;
int ret;
+ int max_tokens = TOKEN_BLOCK_SIZE;
+ size_t buf_free = 0;
line = 1;
level = -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_tokens < WPS_MAX_TOKENS - 1
+ while(*wps_bufptr && !fail
&& 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++)
{
@@ -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 */
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;
#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)
{
- skin_buffer_increment(ret);
+ skin_buffer_increment(ret, true);
loaded = true;
}
else
diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h
index 0adae04..20a9dde 100644
--- a/apps/gui/skin_engine/wps_internals.h
+++ b/apps/gui/skin_engine/wps_internals.h
@@ -276,7 +276,7 @@ struct wps_data
/* Total number of tokens in the WPS. During WPS parsing, this is
the index of the token being parsed. */
int num_tokens;
- struct wps_token tokens[WPS_MAX_TOKENS];
+ struct wps_token *tokens;
struct skin_token_list *strings;