diff options
author | Thomas Martitz <kugel@rockbox.org> | 2014-01-11 19:17:58 +0100 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2014-01-11 19:17:58 +0100 |
commit | 26b317e094a37c43d23e661cf99fe858c159f1b2 (patch) | |
tree | 7e0cfbb80fee1b15435a6a261d99186dac2e0455 | |
parent | 2a471c9e84ddc4f6f407d4fe3ad2a21a1d0e3723 (diff) | |
download | rockbox-26b317e094a37c43d23e661cf99fe858c159f1b2.tar.gz rockbox-26b317e094a37c43d23e661cf99fe858c159f1b2.zip |
scroll engine: Factor out renderer function so it can be called by lcd code.
This is used by lcd_puts_scroll_worker() to render the line immediately
instead of waiting for the next scroll tick when only the text was updated.
Previously lcd_puts_scroll_worker() did not render anything in this case
which could lead to visible blinking.
This fixes blinking scrolling lines with dynamic text in the skin engine.
Change-Id: I475bde8c8eb7c92f505e3c5ecf4d32bb90690536
-rw-r--r-- | firmware/drivers/lcd-bitmap-common.c | 3 | ||||
-rw-r--r-- | firmware/drivers/lcd-scroll.c | 125 | ||||
-rw-r--r-- | firmware/export/scroll_engine.h | 5 |
3 files changed, 80 insertions, 53 deletions
diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index a102eaea66..a71f5b2862 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c | |||
@@ -398,6 +398,9 @@ static void LCDFN(puts_scroll_worker)(int x, int y, const unsigned char *string, | |||
398 | s->height = height; | 398 | s->height = height; |
399 | s->vp = current_vp; | 399 | s->vp = current_vp; |
400 | LCDFN(scroll_info).lines++; | 400 | LCDFN(scroll_info).lines++; |
401 | } else { | ||
402 | /* if only the text was updated render immediately */ | ||
403 | LCDFN(scroll_now(s)); | ||
401 | } | 404 | } |
402 | } | 405 | } |
403 | 406 | ||
diff --git a/firmware/drivers/lcd-scroll.c b/firmware/drivers/lcd-scroll.c index d524ce81c8..a1bde9fe12 100644 --- a/firmware/drivers/lcd-scroll.c +++ b/firmware/drivers/lcd-scroll.c | |||
@@ -123,11 +123,78 @@ void LCDFN(jump_scroll_delay)(int ms) | |||
123 | } | 123 | } |
124 | #endif | 124 | #endif |
125 | 125 | ||
126 | /* This renders the scrolling line described by s immediatly. | ||
127 | * This can be called to update a scrolling line if the text has changed | ||
128 | * without waiting for the next scroll tick | ||
129 | * | ||
130 | * Returns true if the text scrolled to the end */ | ||
131 | bool LCDFN(scroll_now)(struct scrollinfo *s) | ||
132 | { | ||
133 | int width = LCDFN(getstringsize)(s->linebuffer, NULL, NULL); | ||
134 | bool ended = false; | ||
135 | /* assume s->scroll_func() don't yield; otherwise this buffer might need | ||
136 | * to be mutex'd (the worst case would be minor glitches though) */ | ||
137 | static char line_buf[SCROLL_LINE_SIZE]; | ||
138 | |||
139 | if (s->bidir) | ||
140 | { /* scroll bidirectional */ | ||
141 | s->line = s->linebuffer; | ||
142 | if (s->offset <= 0) { | ||
143 | /* at beginning of line */ | ||
144 | s->offset = 0; | ||
145 | s->backward = false; | ||
146 | ended = true; | ||
147 | } | ||
148 | else if (s->offset >= width - s->width) { | ||
149 | /* at end of line */ | ||
150 | s->offset = width - s->width; | ||
151 | s->backward = true; | ||
152 | ended = true; | ||
153 | } | ||
154 | } | ||
155 | else | ||
156 | { | ||
157 | snprintf(line_buf, sizeof(line_buf)-1, "%s%s%s", | ||
158 | s->linebuffer, " ", s->linebuffer); | ||
159 | s->line = line_buf; | ||
160 | width += LCDFN(getstringsize)(" ", NULL, NULL); | ||
161 | /* scroll forward the whole time */ | ||
162 | if (s->offset >= width) { | ||
163 | s->offset = 0; | ||
164 | ended = true; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | /* Stash and restore these three, so that the scroll_func | ||
169 | * can do whatever it likes without destroying the state */ | ||
170 | #ifdef HAVE_LCD_BITMAP | ||
171 | unsigned drawmode; | ||
172 | #if LCD_DEPTH > 1 | ||
173 | unsigned fg_pattern, bg_pattern; | ||
174 | fg_pattern = s->vp->fg_pattern; | ||
175 | bg_pattern = s->vp->bg_pattern; | ||
176 | #endif | ||
177 | drawmode = s->vp->drawmode; | ||
178 | #endif | ||
179 | s->scroll_func(s); | ||
180 | |||
181 | LCDFN(update_viewport_rect)(s->x, s->y, s->width, s->height); | ||
182 | |||
183 | #ifdef HAVE_LCD_BITMAP | ||
184 | #if LCD_DEPTH > 1 | ||
185 | s->vp->fg_pattern = fg_pattern; | ||
186 | s->vp->bg_pattern = bg_pattern; | ||
187 | #endif | ||
188 | s->vp->drawmode = drawmode; | ||
189 | #endif | ||
190 | |||
191 | return ended; | ||
192 | } | ||
193 | |||
126 | static void LCDFN(scroll_worker)(void) | 194 | static void LCDFN(scroll_worker)(void) |
127 | { | 195 | { |
128 | int index, width; | 196 | int index; |
129 | bool makedelay; | 197 | bool makedelay; |
130 | static char line_buf[SCROLL_LINE_SIZE]; | ||
131 | bool is_default; | 198 | bool is_default; |
132 | struct scroll_screen_info *si = &LCDFN(scroll_info); | 199 | struct scroll_screen_info *si = &LCDFN(scroll_info); |
133 | struct scrollinfo *s; | 200 | struct scrollinfo *s; |
@@ -152,7 +219,6 @@ static void LCDFN(scroll_worker)(void) | |||
152 | vp = LCDFN(get_viewport)(&is_default); | 219 | vp = LCDFN(get_viewport)(&is_default); |
153 | LCDFN(set_viewport)(s->vp); | 220 | LCDFN(set_viewport)(s->vp); |
154 | 221 | ||
155 | width = LCDFN(getstringsize)(s->linebuffer, NULL, NULL); | ||
156 | makedelay = false; | 222 | makedelay = false; |
157 | #ifdef HAVE_LCD_BITMAP | 223 | #ifdef HAVE_LCD_BITMAP |
158 | step = si->step; | 224 | step = si->step; |
@@ -160,62 +226,15 @@ static void LCDFN(scroll_worker)(void) | |||
160 | step = 1; | 226 | step = 1; |
161 | #endif | 227 | #endif |
162 | 228 | ||
229 | |||
163 | if (s->backward) | 230 | if (s->backward) |
164 | s->offset -= step; | 231 | s->offset -= step; |
165 | else | 232 | else |
166 | s->offset += step; | 233 | s->offset += step; |
167 | 234 | ||
168 | if (s->bidir) | 235 | /* put the line onto the display now */ |
169 | { /* scroll bidirectional */ | 236 | makedelay = LCDFN(scroll_now(s)); |
170 | s->line = s->linebuffer; | ||
171 | if (s->offset <= 0) { | ||
172 | /* at beginning of line */ | ||
173 | s->offset = 0; | ||
174 | s->backward = false; | ||
175 | makedelay = true; | ||
176 | } | ||
177 | else if (s->offset >= width - s->width) { | ||
178 | /* at end of line */ | ||
179 | s->offset = width - s->width; | ||
180 | s->backward = true; | ||
181 | makedelay = true; | ||
182 | } | ||
183 | } | ||
184 | else | ||
185 | { | ||
186 | snprintf(line_buf, sizeof(line_buf)-1, "%s%s%s", | ||
187 | s->linebuffer, " ", s->linebuffer); | ||
188 | s->line = line_buf; | ||
189 | width += LCDFN(getstringsize)(" ", NULL, NULL); | ||
190 | /* scroll forward the whole time */ | ||
191 | if (s->offset >= width) { | ||
192 | s->offset = 0; | ||
193 | makedelay = true; | ||
194 | } | ||
195 | } | ||
196 | 237 | ||
197 | /* Stash and restore these three, so that the scroll_func | ||
198 | * can do whatever it likes without destroying the state */ | ||
199 | #ifdef HAVE_LCD_BITMAP | ||
200 | unsigned drawmode; | ||
201 | #if LCD_DEPTH > 1 | ||
202 | unsigned fg_pattern, bg_pattern; | ||
203 | fg_pattern = s->vp->fg_pattern; | ||
204 | bg_pattern = s->vp->bg_pattern; | ||
205 | #endif | ||
206 | drawmode = s->vp->drawmode; | ||
207 | #endif | ||
208 | s->scroll_func(s); | ||
209 | |||
210 | LCDFN(update_viewport_rect)(s->x, s->y, s->width, s->height); | ||
211 | |||
212 | #ifdef HAVE_LCD_BITMAP | ||
213 | #if LCD_DEPTH > 1 | ||
214 | s->vp->fg_pattern = fg_pattern; | ||
215 | s->vp->bg_pattern = bg_pattern; | ||
216 | #endif | ||
217 | s->vp->drawmode = drawmode; | ||
218 | #endif | ||
219 | LCDFN(set_viewport)(vp); | 238 | LCDFN(set_viewport)(vp); |
220 | 239 | ||
221 | if (makedelay) | 240 | if (makedelay) |
diff --git a/firmware/export/scroll_engine.h b/firmware/export/scroll_engine.h index 19a2bc4cca..64e1d6d6ae 100644 --- a/firmware/export/scroll_engine.h +++ b/firmware/export/scroll_engine.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #include "file.h" | 30 | #include "file.h" |
31 | 31 | ||
32 | struct viewport; | 32 | struct viewport; |
33 | struct scrollinfo; | ||
33 | 34 | ||
34 | extern void scroll_init(void) INIT_ATTR; | 35 | extern void scroll_init(void) INIT_ATTR; |
35 | 36 | ||
@@ -40,6 +41,7 @@ extern void lcd_scroll_delay(int ms); | |||
40 | extern void lcd_scroll_stop(void); | 41 | extern void lcd_scroll_stop(void); |
41 | extern void lcd_scroll_stop_viewport(const struct viewport *vp); | 42 | extern void lcd_scroll_stop_viewport(const struct viewport *vp); |
42 | extern void lcd_scroll_stop_viewport_rect(const struct viewport *vp, int x, int y, int width, int height); | 43 | extern void lcd_scroll_stop_viewport_rect(const struct viewport *vp, int x, int y, int width, int height); |
44 | extern bool lcd_scroll_now(struct scrollinfo *scroll); | ||
43 | #ifdef HAVE_REMOTE_LCD | 45 | #ifdef HAVE_REMOTE_LCD |
44 | extern void lcd_remote_scroll_speed(int speed); | 46 | extern void lcd_remote_scroll_speed(int speed); |
45 | extern void lcd_remote_scroll_delay(int ms); | 47 | extern void lcd_remote_scroll_delay(int ms); |
@@ -47,8 +49,11 @@ extern void lcd_remote_scroll_delay(int ms); | |||
47 | extern void lcd_remote_scroll_stop(void); | 49 | extern void lcd_remote_scroll_stop(void); |
48 | extern void lcd_remote_scroll_stop_viewport(const struct viewport *vp); | 50 | extern void lcd_remote_scroll_stop_viewport(const struct viewport *vp); |
49 | extern void lcd_remote_scroll_stop_viewport_rect(const struct viewport *vp, int x, int y, int width, int height); | 51 | extern void lcd_remote_scroll_stop_viewport_rect(const struct viewport *vp, int x, int y, int width, int height); |
52 | extern bool lcd_remote_scroll_now(struct scrollinfo *scroll); | ||
50 | #endif | 53 | #endif |
51 | 54 | ||
55 | |||
56 | |||
52 | /* internal usage, but in multiple drivers | 57 | /* internal usage, but in multiple drivers |
53 | * larger than the normal linebuffer since it holds the line a second | 58 | * larger than the normal linebuffer since it holds the line a second |
54 | * time (+3 spaces) for non-bidir scrolling */ | 59 | * time (+3 spaces) for non-bidir scrolling */ |