From 45b2d8802d1e8fcc47fd1148adb7b1173ad5b311 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Sat, 22 Mar 2008 00:31:22 +0000 Subject: 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 --- apps/gui/gwps-common.c | 70 ++++++++++++++++++++++++-------------------------- apps/gui/gwps.h | 24 +++++++++-------- apps/gui/wps_debug.c | 7 ++--- apps/gui/wps_parser.c | 36 ++++++++++++++------------ 4 files changed, 70 insertions(+), 67 deletions(-) diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index ae5492a66c..3c3bad3056 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c @@ -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. */ static bool get_line(struct gui_wps *gwps, - int v, int line, int subline, + int line, int subline, struct align_pos *align, char *linebuf, int linebuf_size) @@ -1494,8 +1494,8 @@ static bool get_line(struct gui_wps *gwps, #endif /* Process all tokens of the desired subline */ - last_token_idx = wps_last_token_index(data, v, line, subline); - for (i = wps_first_token_index(data, v, line, subline); + last_token_idx = wps_last_token_index(data, line, subline); + for (i = wps_first_token_index(data, line, subline); i <= last_token_idx; i++) { switch(data->tokens[i].type) @@ -1594,16 +1594,16 @@ static bool get_line(struct gui_wps *gwps, 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; int i; - int subline_idx = wps_subline_index(data, v, line, subline); - int last_token_idx = wps_last_token_index(data, v, line, subline); + int subline_idx = wps_subline_index(data, line, subline); + int last_token_idx = wps_last_token_index(data, line, subline); 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++) { 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 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; @@ -1640,13 +1640,13 @@ static bool update_curr_subline(struct gui_wps *gwps, int v, int line) bool new_subline_refresh; bool only_one_subline; - num_sublines = data->viewports[v].lines[line].num_sublines; - reset_subline = (data->viewports[v].lines[line].curr_subline == SUBLINE_RESET); + num_sublines = data->lines[line].num_sublines; + reset_subline = (data->lines[line].curr_subline == SUBLINE_RESET); new_subline_refresh = false; only_one_subline = false; /* 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) { /* 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) search_start = 0; else - search_start = data->viewports[v].lines[line].curr_subline; + search_start = data->lines[line].curr_subline; 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 */ - 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; - data->viewports[v].lines[line].curr_subline = 0; + data->lines[line].curr_subline = 0; } /* if back where we started after search or only one subline is defined on the line */ if (((search > 0) && - (data->viewports[v].lines[line].curr_subline == search_start)) || + (data->lines[line].curr_subline == search_start)) || only_one_subline) { /* 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 : - data->viewports[v].lines[line].subline_expire_time) + 100 * HZ; + data->lines[line].subline_expire_time) + 100 * HZ; break; } else { /* 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, - data->viewports[v].lines[line].curr_subline); + int subline_idx = wps_subline_index(data, line, + data->lines[line].curr_subline); /* only use this subline if subline time > 0 */ if (data->sublines[subline_idx].time_mult > 0) { new_subline_refresh = true; - data->viewports[v].lines[line].subline_expire_time = (reset_subline ? - current_tick : data->viewports[v].lines[line].subline_expire_time) + + data->lines[line].subline_expire_time = (reset_subline ? + current_tick : data->lines[line].subline_expire_time) + BASE_SUBLINE_TIME*data->sublines[subline_idx].time_mult; break; } @@ -1909,12 +1909,9 @@ bool gui_wps_refresh(struct gui_wps *gwps, { 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->viewports[v].lines[i].curr_subline = SUBLINE_RESET; - } + data->lines[i].curr_subline = SUBLINE_RESET; } } @@ -1951,23 +1948,24 @@ bool gui_wps_refresh(struct gui_wps *gwps, } #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)); update_line = false; /* 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, - data->viewports[v].lines[line].curr_subline); + subline_idx = wps_subline_index(data, line, + data->lines[line].curr_subline); flags = data->sublines[subline_idx].line_type; if (refresh_mode == WPS_REFRESH_ALL || (flags & refresh_mode) || new_subline_refresh) { /* 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)); } @@ -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 too often, so that it has the time to scroll */ 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 - write_line(display, &align, line, false); + write_line(display, &align, line - data->viewports[v].first_line, false); } } diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h index d31471c2a4..e72b41308b 100644 --- a/apps/gui/gwps.h +++ b/apps/gui/gwps.h @@ -88,7 +88,7 @@ struct align_pos { + (2*LCD_HEIGHT*LCD_WIDTH/8)) #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_TOKENS 1024 #define WPS_MAX_STRINGS 128 @@ -321,10 +321,9 @@ struct wps_line { struct wps_viewport { struct viewport vp; /* The LCD viewport struct */ - /* Number of lines in this viewport. During WPS parsing, this is - the index of the line being parsed. */ - int num_lines; - struct wps_line lines[WPS_MAX_LINES]; + /* Indexes of the first and last lines belonging to this viewport in the + lines[] array */ + int first_line, last_line; }; /* wps_data @@ -371,10 +370,16 @@ struct wps_data bool remote_wps; #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 */ int num_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 the index of the subline where the parsed tokens are added to. */ int num_sublines; @@ -403,25 +408,22 @@ bool wps_data_load(struct wps_data *wps_data, bool isfile); /* Returns the index of the subline in the subline array - v - 0-based viewport number line - 0-based line number 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 - v - 0-based viewport number line - 0-based line number 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. - v - 0-based viewport number line - 0-based line number 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 */ diff --git a/apps/gui/wps_debug.c b/apps/gui/wps_debug.c index 0c13fd2c22..9bff1d23ae 100644 --- a/apps/gui/wps_debug.c +++ b/apps/gui/wps_debug.c @@ -502,7 +502,8 @@ static void print_line_info(struct wps_data *data) DEBUGF("Number of viewports : %d\n", data->num_viewports); 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 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.width, 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", 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", 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) DEBUGF(", scrolled"); diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c index c641f2c247..be3d2fb882 100644 --- a/apps/gui/wps_parser.c +++ b/apps/gui/wps_parser.c @@ -338,11 +338,9 @@ static int skip_end_of_line(const char *wps_bufptr) /* Starts a new subline in the current line during parsing */ static void wps_start_new_subline(struct wps_data *data) { - struct wps_viewport* vp = &data->viewports[data->num_viewports]; - data->num_sublines++; 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 @@ -585,12 +583,14 @@ static int parse_viewport(const char *wps_bufptr, } } #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) { - 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->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 */ return skip_end_of_line(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 && 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++) { @@ -1180,12 +1180,12 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr) line++; 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->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->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 */ 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 */ 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; } -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; if (idx < data->num_sublines - 1) { -- cgit v1.2.3