1
0
Fork 0
forked from len0rd/rockbox

Reduce the shocking amount of RAM my viewports implementation was using. The first version stored an array of lines for each of the 16 possible viewports (MAX_VIEWPORTS * the number of lines on the LCD with a 5-pixel high font). This version reverts back to a single global array of lines, with each viewport specifying the first and last lines as indexes into that array. This also turns out to be simpler, reducing binsize a little as well.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16735 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Dave Chapman 2008-03-22 00:31:22 +00:00
parent 7ee63e22c5
commit 45b2d8802d
4 changed files with 70 additions and 67 deletions

View file

@ -1466,7 +1466,7 @@ static bool evaluate_conditional(struct gui_wps *gwps, int *token_index)
The return value indicates whether the line needs to be updated. The return value indicates whether the line needs to be updated.
*/ */
static bool get_line(struct gui_wps *gwps, static bool get_line(struct gui_wps *gwps,
int v, int line, int subline, int line, int subline,
struct align_pos *align, struct align_pos *align,
char *linebuf, char *linebuf,
int linebuf_size) int linebuf_size)
@ -1494,8 +1494,8 @@ static bool get_line(struct gui_wps *gwps,
#endif #endif
/* Process all tokens of the desired subline */ /* Process all tokens of the desired subline */
last_token_idx = wps_last_token_index(data, v, line, subline); last_token_idx = wps_last_token_index(data, line, subline);
for (i = wps_first_token_index(data, v, line, subline); for (i = wps_first_token_index(data, line, subline);
i <= last_token_idx; i++) i <= last_token_idx; i++)
{ {
switch(data->tokens[i].type) switch(data->tokens[i].type)
@ -1594,16 +1594,16 @@ static bool get_line(struct gui_wps *gwps,
return update; return update;
} }
static void get_subline_timeout(struct gui_wps *gwps, int v, int line, int subline) static void get_subline_timeout(struct gui_wps *gwps, int line, int subline)
{ {
struct wps_data *data = gwps->data; struct wps_data *data = gwps->data;
int i; int i;
int subline_idx = wps_subline_index(data, v, line, subline); int subline_idx = wps_subline_index(data, line, subline);
int last_token_idx = wps_last_token_index(data, v, line, subline); int last_token_idx = wps_last_token_index(data, line, subline);
data->sublines[subline_idx].time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER; data->sublines[subline_idx].time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER;
for (i = wps_first_token_index(data, v, line, subline); for (i = wps_first_token_index(data, line, subline);
i <= last_token_idx; i++) i <= last_token_idx; i++)
{ {
switch(data->tokens[i].type) switch(data->tokens[i].type)
@ -1631,7 +1631,7 @@ static void get_subline_timeout(struct gui_wps *gwps, int v, int line, int subli
/* Calculates which subline should be displayed for the specified line /* Calculates which subline should be displayed for the specified line
Returns true iff the subline must be refreshed */ Returns true iff the subline must be refreshed */
static bool update_curr_subline(struct gui_wps *gwps, int v, int line) static bool update_curr_subline(struct gui_wps *gwps, int line)
{ {
struct wps_data *data = gwps->data; struct wps_data *data = gwps->data;
@ -1640,13 +1640,13 @@ static bool update_curr_subline(struct gui_wps *gwps, int v, int line)
bool new_subline_refresh; bool new_subline_refresh;
bool only_one_subline; bool only_one_subline;
num_sublines = data->viewports[v].lines[line].num_sublines; num_sublines = data->lines[line].num_sublines;
reset_subline = (data->viewports[v].lines[line].curr_subline == SUBLINE_RESET); reset_subline = (data->lines[line].curr_subline == SUBLINE_RESET);
new_subline_refresh = false; new_subline_refresh = false;
only_one_subline = false; only_one_subline = false;
/* if time to advance to next sub-line */ /* if time to advance to next sub-line */
if (TIME_AFTER(current_tick, data->viewports[v].lines[line].subline_expire_time - 1) || if (TIME_AFTER(current_tick, data->lines[line].subline_expire_time - 1) ||
reset_subline) reset_subline)
{ {
/* search all sublines until the next subline with time > 0 /* search all sublines until the next subline with time > 0
@ -1654,46 +1654,46 @@ static bool update_curr_subline(struct gui_wps *gwps, int v, int line)
if (reset_subline) if (reset_subline)
search_start = 0; search_start = 0;
else else
search_start = data->viewports[v].lines[line].curr_subline; search_start = data->lines[line].curr_subline;
for (search = 0; search < num_sublines; search++) for (search = 0; search < num_sublines; search++)
{ {
data->viewports[v].lines[line].curr_subline++; data->lines[line].curr_subline++;
/* wrap around if beyond last defined subline or WPS_MAX_SUBLINES */ /* wrap around if beyond last defined subline or WPS_MAX_SUBLINES */
if (data->viewports[v].lines[line].curr_subline == num_sublines) if (data->lines[line].curr_subline == num_sublines)
{ {
if (data->viewports[v].lines[line].curr_subline == 1) if (data->lines[line].curr_subline == 1)
only_one_subline = true; only_one_subline = true;
data->viewports[v].lines[line].curr_subline = 0; data->lines[line].curr_subline = 0;
} }
/* if back where we started after search or /* if back where we started after search or
only one subline is defined on the line */ only one subline is defined on the line */
if (((search > 0) && if (((search > 0) &&
(data->viewports[v].lines[line].curr_subline == search_start)) || (data->lines[line].curr_subline == search_start)) ||
only_one_subline) only_one_subline)
{ {
/* no other subline with a time > 0 exists */ /* no other subline with a time > 0 exists */
data->viewports[v].lines[line].subline_expire_time = (reset_subline ? data->lines[line].subline_expire_time = (reset_subline ?
current_tick : current_tick :
data->viewports[v].lines[line].subline_expire_time) + 100 * HZ; data->lines[line].subline_expire_time) + 100 * HZ;
break; break;
} }
else else
{ {
/* get initial time multiplier for this subline */ /* get initial time multiplier for this subline */
get_subline_timeout(gwps, v, line, data->viewports[v].lines[line].curr_subline); get_subline_timeout(gwps, line, data->lines[line].curr_subline);
int subline_idx = wps_subline_index(data, v, line, int subline_idx = wps_subline_index(data, line,
data->viewports[v].lines[line].curr_subline); data->lines[line].curr_subline);
/* only use this subline if subline time > 0 */ /* only use this subline if subline time > 0 */
if (data->sublines[subline_idx].time_mult > 0) if (data->sublines[subline_idx].time_mult > 0)
{ {
new_subline_refresh = true; new_subline_refresh = true;
data->viewports[v].lines[line].subline_expire_time = (reset_subline ? data->lines[line].subline_expire_time = (reset_subline ?
current_tick : data->viewports[v].lines[line].subline_expire_time) + current_tick : data->lines[line].subline_expire_time) +
BASE_SUBLINE_TIME*data->sublines[subline_idx].time_mult; BASE_SUBLINE_TIME*data->sublines[subline_idx].time_mult;
break; break;
} }
@ -1909,12 +1909,9 @@ bool gui_wps_refresh(struct gui_wps *gwps,
{ {
display->clear_display(); display->clear_display();
for (v = 0; v < data->num_viewports; v++) for (i = 0; i <= data->num_lines; i++)
{ {
for (i = 0; i < data->viewports[v].num_lines; i++) data->lines[i].curr_subline = SUBLINE_RESET;
{
data->viewports[v].lines[i].curr_subline = SUBLINE_RESET;
}
} }
} }
@ -1951,23 +1948,24 @@ bool gui_wps_refresh(struct gui_wps *gwps,
} }
#endif #endif
for (line = 0; line < data->viewports[v].num_lines; line++) for (line = data->viewports[v].first_line;
line <= data->viewports[v].last_line; line++)
{ {
memset(linebuf, 0, sizeof(linebuf)); memset(linebuf, 0, sizeof(linebuf));
update_line = false; update_line = false;
/* get current subline for the line */ /* get current subline for the line */
new_subline_refresh = update_curr_subline(gwps, v, line); new_subline_refresh = update_curr_subline(gwps, line);
subline_idx = wps_subline_index(data, v, line, subline_idx = wps_subline_index(data, line,
data->viewports[v].lines[line].curr_subline); data->lines[line].curr_subline);
flags = data->sublines[subline_idx].line_type; flags = data->sublines[subline_idx].line_type;
if (refresh_mode == WPS_REFRESH_ALL || (flags & refresh_mode) if (refresh_mode == WPS_REFRESH_ALL || (flags & refresh_mode)
|| new_subline_refresh) || new_subline_refresh)
{ {
/* get_line tells us if we need to update the line */ /* get_line tells us if we need to update the line */
update_line = get_line(gwps, v, line, data->viewports[v].lines[line].curr_subline, update_line = get_line(gwps, line, data->lines[line].curr_subline,
&align, linebuf, sizeof(linebuf)); &align, linebuf, sizeof(linebuf));
} }
@ -2021,10 +2019,10 @@ bool gui_wps_refresh(struct gui_wps *gwps,
/* if the line is a scrolling one we don't want to update /* if the line is a scrolling one we don't want to update
too often, so that it has the time to scroll */ too often, so that it has the time to scroll */
if ((refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh) if ((refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh)
write_line(display, &align, line, true); write_line(display, &align, line - data->viewports[v].first_line, true);
} }
else else
write_line(display, &align, line, false); write_line(display, &align, line - data->viewports[v].first_line, false);
} }
} }

View file

@ -88,7 +88,7 @@ struct align_pos {
+ (2*LCD_HEIGHT*LCD_WIDTH/8)) + (2*LCD_HEIGHT*LCD_WIDTH/8))
#define WPS_MAX_VIEWPORTS 16 #define WPS_MAX_VIEWPORTS 16
#define WPS_MAX_LINES (LCD_HEIGHT/5+1) #define WPS_MAX_LINES ((LCD_HEIGHT/5+1) * 2)
#define WPS_MAX_SUBLINES (WPS_MAX_LINES*3) #define WPS_MAX_SUBLINES (WPS_MAX_LINES*3)
#define WPS_MAX_TOKENS 1024 #define WPS_MAX_TOKENS 1024
#define WPS_MAX_STRINGS 128 #define WPS_MAX_STRINGS 128
@ -321,10 +321,9 @@ struct wps_line {
struct wps_viewport { struct wps_viewport {
struct viewport vp; /* The LCD viewport struct */ struct viewport vp; /* The LCD viewport struct */
/* Number of lines in this viewport. During WPS parsing, this is /* Indexes of the first and last lines belonging to this viewport in the
the index of the line being parsed. */ lines[] array */
int num_lines; int first_line, last_line;
struct wps_line lines[WPS_MAX_LINES];
}; };
/* wps_data /* wps_data
@ -371,10 +370,16 @@ struct wps_data
bool remote_wps; bool remote_wps;
#endif #endif
/* Number of lines in the WPS. During WPS parsing, this is
the index of the line being parsed. */
int num_lines;
/* Number of viewports in the WPS */ /* Number of viewports in the WPS */
int num_viewports; int num_viewports;
struct wps_viewport viewports[WPS_MAX_VIEWPORTS]; struct wps_viewport viewports[WPS_MAX_VIEWPORTS];
struct wps_line lines[WPS_MAX_LINES];
/* Total number of sublines in the WPS. During WPS parsing, this is /* Total number of sublines in the WPS. During WPS parsing, this is
the index of the subline where the parsed tokens are added to. */ the index of the subline where the parsed tokens are added to. */
int num_sublines; int num_sublines;
@ -403,25 +408,22 @@ bool wps_data_load(struct wps_data *wps_data,
bool isfile); bool isfile);
/* Returns the index of the subline in the subline array /* Returns the index of the subline in the subline array
v - 0-based viewport number
line - 0-based line number line - 0-based line number
subline - 0-based subline number within the line subline - 0-based subline number within the line
*/ */
int wps_subline_index(struct wps_data *wps_data, int v, int line, int subline); int wps_subline_index(struct wps_data *wps_data, int line, int subline);
/* Returns the index of the first subline's token in the token array /* Returns the index of the first subline's token in the token array
v - 0-based viewport number
line - 0-based line number line - 0-based line number
subline - 0-based subline number within the line subline - 0-based subline number within the line
*/ */
int wps_first_token_index(struct wps_data *data, int v, int line, int subline); int wps_first_token_index(struct wps_data *data, int line, int subline);
/* Returns the index of the last subline's token in the token array. /* Returns the index of the last subline's token in the token array.
v - 0-based viewport number
line - 0-based line number line - 0-based line number
subline - 0-based subline number within the line subline - 0-based subline number within the line
*/ */
int wps_last_token_index(struct wps_data *data, int v, int line, int subline); int wps_last_token_index(struct wps_data *data, int line, int subline);
/* wps_data end */ /* wps_data end */

View file

@ -502,7 +502,8 @@ static void print_line_info(struct wps_data *data)
DEBUGF("Number of viewports : %d\n", data->num_viewports); DEBUGF("Number of viewports : %d\n", data->num_viewports);
for (v = 0; v < data->num_viewports; v++) for (v = 0; v < data->num_viewports; v++)
{ {
DEBUGF("vp %d: Number of lines: %d\n", v, data->viewports[v].num_lines); DEBUGF("vp %d: First line: %d\n", v, data->viewports[v].first_line);
DEBUGF("vp %d: Last line: %d\n", v, data->viewports[v].last_line);
} }
DEBUGF("Number of sublines : %d\n", data->num_sublines); DEBUGF("Number of sublines : %d\n", data->num_sublines);
DEBUGF("Number of tokens : %d\n", data->num_tokens); DEBUGF("Number of tokens : %d\n", data->num_tokens);
@ -517,7 +518,7 @@ static void print_line_info(struct wps_data *data)
data->viewports[v].vp.y, data->viewports[v].vp.y,
data->viewports[v].vp.width, data->viewports[v].vp.width,
data->viewports[v].vp.height); data->viewports[v].vp.height);
for (i = 0, line = data->viewports[v].lines; i < data->viewports[v].num_lines; i++,line++) for (i = data->viewports[v].first_line, line = &data->lines[data->viewports[v].first_line]; i <= data->viewports[v].last_line; i++,line++)
{ {
DEBUGF("Line %2d (num_sublines=%d, first_subline=%d)\n", DEBUGF("Line %2d (num_sublines=%d, first_subline=%d)\n",
i, line->num_sublines, line->first_subline_idx); i, line->num_sublines, line->first_subline_idx);
@ -527,7 +528,7 @@ static void print_line_info(struct wps_data *data)
{ {
DEBUGF(" Subline %d: first_token=%3d, last_token=%3d", DEBUGF(" Subline %d: first_token=%3d, last_token=%3d",
j, subline->first_token_idx, j, subline->first_token_idx,
wps_last_token_index(data, v, i, j)); wps_last_token_index(data, i, j));
if (subline->line_type & WPS_REFRESH_SCROLL) if (subline->line_type & WPS_REFRESH_SCROLL)
DEBUGF(", scrolled"); DEBUGF(", scrolled");

View file

@ -338,11 +338,9 @@ static int skip_end_of_line(const char *wps_bufptr)
/* Starts a new subline in the current line during parsing */ /* Starts a new subline in the current line during parsing */
static void wps_start_new_subline(struct wps_data *data) static void wps_start_new_subline(struct wps_data *data)
{ {
struct wps_viewport* vp = &data->viewports[data->num_viewports];
data->num_sublines++; data->num_sublines++;
data->sublines[data->num_sublines].first_token_idx = data->num_tokens; data->sublines[data->num_sublines].first_token_idx = data->num_tokens;
vp->lines[vp->num_lines].num_sublines++; data->lines[data->num_lines].num_sublines++;
} }
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
@ -585,12 +583,14 @@ static int parse_viewport(const char *wps_bufptr,
} }
} }
#endif #endif
wps_data->viewports[wps_data->num_viewports].num_lines = 0; wps_data->viewports[wps_data->num_viewports-1].last_line = wps_data->num_lines - 1;
wps_data->viewports[wps_data->num_viewports].first_line = wps_data->num_lines;
if (wps_data->num_sublines < WPS_MAX_SUBLINES) if (wps_data->num_sublines < WPS_MAX_SUBLINES)
{ {
wps_data->viewports[wps_data->num_viewports].lines[0].first_subline_idx = wps_data->lines[wps_data->num_lines].first_subline_idx =
wps_data->num_sublines; wps_data->num_sublines;
wps_data->sublines[wps_data->num_sublines].first_token_idx = wps_data->sublines[wps_data->num_sublines].first_token_idx =
@ -599,7 +599,7 @@ static int parse_viewport(const char *wps_bufptr,
/* Skip the rest of the line */ /* Skip the rest of the line */
return skip_end_of_line(wps_bufptr); return skip_end_of_line(wps_bufptr);
} }
static int parse_image_special(const char *wps_bufptr, static int parse_image_special(const char *wps_bufptr,
@ -1072,7 +1072,7 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
while(*wps_bufptr && !fail && data->num_tokens < WPS_MAX_TOKENS - 1 while(*wps_bufptr && !fail && data->num_tokens < WPS_MAX_TOKENS - 1
&& data->num_viewports < WPS_MAX_VIEWPORTS && data->num_viewports < WPS_MAX_VIEWPORTS
&& data->viewports[data->num_viewports].num_lines < WPS_MAX_LINES) && data->num_lines < WPS_MAX_LINES)
{ {
switch(*wps_bufptr++) switch(*wps_bufptr++)
{ {
@ -1180,12 +1180,12 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
line++; line++;
wps_start_new_subline(data); wps_start_new_subline(data);
data->viewports[data->num_viewports].num_lines++; /* Start a new line */ data->num_lines++; /* Start a new line */
if ((data->viewports[data->num_viewports].num_lines < WPS_MAX_LINES) && if ((data->num_lines < WPS_MAX_LINES) &&
(data->num_sublines < WPS_MAX_SUBLINES)) (data->num_sublines < WPS_MAX_SUBLINES))
{ {
data->viewports[data->num_viewports].lines[data->viewports[data->num_viewports].num_lines].first_subline_idx = data->lines[data->num_lines].first_subline_idx =
data->num_sublines; data->num_sublines;
data->sublines[data->num_sublines].first_token_idx = data->sublines[data->num_sublines].first_token_idx =
@ -1262,6 +1262,8 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
if (!fail && level >= 0) /* there are unclosed conditionals */ if (!fail && level >= 0) /* there are unclosed conditionals */
fail = PARSE_FAIL_UNCLOSED_COND; fail = PARSE_FAIL_UNCLOSED_COND;
data->viewports[data->num_viewports].last_line = data->num_lines - 1;
/* We have finished with the last viewport, so increment count */ /* We have finished with the last viewport, so increment count */
data->num_viewports++; data->num_viewports++;
@ -1512,20 +1514,20 @@ bool wps_data_load(struct wps_data *wps_data,
} }
} }
int wps_subline_index(struct wps_data *data, int v, int line, int subline) int wps_subline_index(struct wps_data *data, int line, int subline)
{ {
return data->viewports[v].lines[line].first_subline_idx + subline; return data->lines[line].first_subline_idx + subline;
} }
int wps_first_token_index(struct wps_data *data, int v, int line, int subline) int wps_first_token_index(struct wps_data *data, int line, int subline)
{ {
int first_subline_idx = data->viewports[v].lines[line].first_subline_idx; int first_subline_idx = data->lines[line].first_subline_idx;
return data->sublines[first_subline_idx + subline].first_token_idx; return data->sublines[first_subline_idx + subline].first_token_idx;
} }
int wps_last_token_index(struct wps_data *data, int v, int line, int subline) int wps_last_token_index(struct wps_data *data, int line, int subline)
{ {
int first_subline_idx = data->viewports[v].lines[line].first_subline_idx; int first_subline_idx = data->lines[line].first_subline_idx;
int idx = first_subline_idx + subline; int idx = first_subline_idx + subline;
if (idx < data->num_sublines - 1) if (idx < data->num_sublines - 1)
{ {