diff options
Diffstat (limited to 'firmware/drivers/lcd-16bit-common.c')
-rw-r--r-- | firmware/drivers/lcd-16bit-common.c | 369 |
1 files changed, 360 insertions, 9 deletions
diff --git a/firmware/drivers/lcd-16bit-common.c b/firmware/drivers/lcd-16bit-common.c index 89d6dce966..7253524976 100644 --- a/firmware/drivers/lcd-16bit-common.c +++ b/firmware/drivers/lcd-16bit-common.c | |||
@@ -28,6 +28,357 @@ | |||
28 | #error ROW_INC or COL_INC not defined | 28 | #error ROW_INC or COL_INC not defined |
29 | #endif | 29 | #endif |
30 | 30 | ||
31 | enum fill_opt { | ||
32 | OPT_NONE = 0, | ||
33 | OPT_SET, | ||
34 | OPT_COPY | ||
35 | }; | ||
36 | |||
37 | /*** globals ***/ | ||
38 | fb_data lcd_framebuffer[LCD_FBHEIGHT][LCD_FBWIDTH] | ||
39 | IRAM_LCDFRAMEBUFFER CACHEALIGN_AT_LEAST_ATTR(16); | ||
40 | |||
41 | |||
42 | static fb_data* lcd_backdrop = NULL; | ||
43 | static long lcd_backdrop_offset IDATA_ATTR = 0; | ||
44 | |||
45 | static struct viewport default_vp = | ||
46 | { | ||
47 | .x = 0, | ||
48 | .y = 0, | ||
49 | .width = LCD_WIDTH, | ||
50 | .height = LCD_HEIGHT, | ||
51 | .font = FONT_SYSFIXED, | ||
52 | .drawmode = DRMODE_SOLID, | ||
53 | .fg_pattern = LCD_DEFAULT_FG, | ||
54 | .bg_pattern = LCD_DEFAULT_BG, | ||
55 | .lss_pattern = LCD_DEFAULT_BG, | ||
56 | .lse_pattern = LCD_DEFAULT_BG, | ||
57 | .lst_pattern = LCD_DEFAULT_BG, | ||
58 | }; | ||
59 | |||
60 | static struct viewport* current_vp IDATA_ATTR = &default_vp; | ||
61 | |||
62 | /* LCD init */ | ||
63 | void lcd_init(void) | ||
64 | { | ||
65 | lcd_clear_display(); | ||
66 | |||
67 | /* Call device specific init */ | ||
68 | lcd_init_device(); | ||
69 | scroll_init(); | ||
70 | } | ||
71 | /*** Viewports ***/ | ||
72 | |||
73 | void lcd_set_viewport(struct viewport* vp) | ||
74 | { | ||
75 | if (vp == NULL) | ||
76 | current_vp = &default_vp; | ||
77 | else | ||
78 | current_vp = vp; | ||
79 | |||
80 | #if defined(SIMULATOR) | ||
81 | /* Force the viewport to be within bounds. If this happens it should | ||
82 | * be considered an error - the viewport will not draw as it might be | ||
83 | * expected. | ||
84 | */ | ||
85 | if((unsigned) current_vp->x > (unsigned) LCD_WIDTH | ||
86 | || (unsigned) current_vp->y > (unsigned) LCD_HEIGHT | ||
87 | || current_vp->x + current_vp->width > LCD_WIDTH | ||
88 | || current_vp->y + current_vp->height > LCD_HEIGHT) | ||
89 | { | ||
90 | #if !defined(HAVE_VIEWPORT_CLIP) | ||
91 | DEBUGF("ERROR: " | ||
92 | #else | ||
93 | DEBUGF("NOTE: " | ||
94 | #endif | ||
95 | "set_viewport out of bounds: x: %d y: %d width: %d height:%d\n", | ||
96 | current_vp->x, current_vp->y, | ||
97 | current_vp->width, current_vp->height); | ||
98 | } | ||
99 | |||
100 | #endif | ||
101 | } | ||
102 | |||
103 | void lcd_update_viewport(void) | ||
104 | { | ||
105 | lcd_update_rect(current_vp->x, current_vp->y, | ||
106 | current_vp->width, current_vp->height); | ||
107 | } | ||
108 | |||
109 | void lcd_update_viewport_rect(int x, int y, int width, int height) | ||
110 | { | ||
111 | lcd_update_rect(current_vp->x + x, current_vp->y + y, width, height); | ||
112 | } | ||
113 | |||
114 | /*** parameter handling ***/ | ||
115 | |||
116 | void lcd_set_drawmode(int mode) | ||
117 | { | ||
118 | current_vp->drawmode = mode & (DRMODE_SOLID|DRMODE_INVERSEVID); | ||
119 | } | ||
120 | |||
121 | int lcd_get_drawmode(void) | ||
122 | { | ||
123 | return current_vp->drawmode; | ||
124 | } | ||
125 | |||
126 | void lcd_set_foreground(unsigned color) | ||
127 | { | ||
128 | current_vp->fg_pattern = color; | ||
129 | } | ||
130 | |||
131 | unsigned lcd_get_foreground(void) | ||
132 | { | ||
133 | return current_vp->fg_pattern; | ||
134 | } | ||
135 | |||
136 | void lcd_set_background(unsigned color) | ||
137 | { | ||
138 | current_vp->bg_pattern = color; | ||
139 | } | ||
140 | |||
141 | unsigned lcd_get_background(void) | ||
142 | { | ||
143 | return current_vp->bg_pattern; | ||
144 | } | ||
145 | |||
146 | void lcd_set_selector_start(unsigned color) | ||
147 | { | ||
148 | current_vp->lss_pattern = color; | ||
149 | } | ||
150 | |||
151 | void lcd_set_selector_end(unsigned color) | ||
152 | { | ||
153 | current_vp->lse_pattern = color; | ||
154 | } | ||
155 | |||
156 | void lcd_set_selector_text(unsigned color) | ||
157 | { | ||
158 | current_vp->lst_pattern = color; | ||
159 | } | ||
160 | |||
161 | void lcd_set_drawinfo(int mode, unsigned fg_color, unsigned bg_color) | ||
162 | { | ||
163 | lcd_set_drawmode(mode); | ||
164 | current_vp->fg_pattern = fg_color; | ||
165 | current_vp->bg_pattern = bg_color; | ||
166 | } | ||
167 | |||
168 | int lcd_getwidth(void) | ||
169 | { | ||
170 | return current_vp->width; | ||
171 | } | ||
172 | |||
173 | int lcd_getheight(void) | ||
174 | { | ||
175 | return current_vp->height; | ||
176 | } | ||
177 | |||
178 | void lcd_setfont(int newfont) | ||
179 | { | ||
180 | current_vp->font = newfont; | ||
181 | } | ||
182 | |||
183 | int lcd_getfont(void) | ||
184 | { | ||
185 | return current_vp->font; | ||
186 | } | ||
187 | |||
188 | int lcd_getstringsize(const unsigned char *str, int *w, int *h) | ||
189 | { | ||
190 | return font_getstringsize(str, w, h, current_vp->font); | ||
191 | } | ||
192 | |||
193 | /*** low-level drawing functions ***/ | ||
194 | |||
195 | static void ICODE_ATTR setpixel(fb_data *address) | ||
196 | { | ||
197 | *address = current_vp->fg_pattern; | ||
198 | } | ||
199 | |||
200 | static void ICODE_ATTR clearpixel(fb_data *address) | ||
201 | { | ||
202 | *address = current_vp->bg_pattern; | ||
203 | } | ||
204 | |||
205 | static void ICODE_ATTR clearimgpixel(fb_data *address) | ||
206 | { | ||
207 | *address = *(fb_data *)((long)address + lcd_backdrop_offset); | ||
208 | } | ||
209 | |||
210 | static void ICODE_ATTR flippixel(fb_data *address) | ||
211 | { | ||
212 | *address = ~(*address); | ||
213 | } | ||
214 | |||
215 | static void ICODE_ATTR nopixel(fb_data *address) | ||
216 | { | ||
217 | (void)address; | ||
218 | } | ||
219 | |||
220 | lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_bgcolor[8] = { | ||
221 | flippixel, nopixel, setpixel, setpixel, | ||
222 | nopixel, clearpixel, nopixel, clearpixel | ||
223 | }; | ||
224 | |||
225 | lcd_fastpixelfunc_type* const lcd_fastpixelfuncs_backdrop[8] = { | ||
226 | flippixel, nopixel, setpixel, setpixel, | ||
227 | nopixel, clearimgpixel, nopixel, clearimgpixel | ||
228 | }; | ||
229 | |||
230 | lcd_fastpixelfunc_type* const * lcd_fastpixelfuncs = lcd_fastpixelfuncs_bgcolor; | ||
231 | |||
232 | void lcd_set_backdrop(fb_data* backdrop) | ||
233 | { | ||
234 | lcd_backdrop = backdrop; | ||
235 | if (backdrop) | ||
236 | { | ||
237 | lcd_backdrop_offset = (long)backdrop - (long)&lcd_framebuffer[0][0]; | ||
238 | lcd_fastpixelfuncs = lcd_fastpixelfuncs_backdrop; | ||
239 | } | ||
240 | else | ||
241 | { | ||
242 | lcd_backdrop_offset = 0; | ||
243 | lcd_fastpixelfuncs = lcd_fastpixelfuncs_bgcolor; | ||
244 | } | ||
245 | } | ||
246 | |||
247 | fb_data* lcd_get_backdrop(void) | ||
248 | { | ||
249 | return lcd_backdrop; | ||
250 | } | ||
251 | |||
252 | /* Clear the whole display */ | ||
253 | void lcd_clear_display(void) | ||
254 | { | ||
255 | struct viewport* old_vp = current_vp; | ||
256 | |||
257 | current_vp = &default_vp; | ||
258 | |||
259 | lcd_clear_viewport(); | ||
260 | |||
261 | current_vp = old_vp; | ||
262 | } | ||
263 | |||
264 | /* Set a single pixel */ | ||
265 | void lcd_drawpixel(int x, int y) | ||
266 | { | ||
267 | if ( ((unsigned)x < (unsigned)current_vp->width) | ||
268 | && ((unsigned)y < (unsigned)current_vp->height) | ||
269 | #if defined(HAVE_VIEWPORT_CLIP) | ||
270 | && ((unsigned)x < (unsigned)LCD_WIDTH) | ||
271 | && ((unsigned)y < (unsigned)LCD_HEIGHT) | ||
272 | #endif | ||
273 | ) | ||
274 | lcd_fastpixelfuncs[current_vp->drawmode](LCDADDR(current_vp->x+x, current_vp->y+y)); | ||
275 | } | ||
276 | |||
277 | /* Draw a line */ | ||
278 | void lcd_drawline(int x1, int y1, int x2, int y2) | ||
279 | { | ||
280 | int numpixels; | ||
281 | int i; | ||
282 | int deltax, deltay; | ||
283 | int d, dinc1, dinc2; | ||
284 | int x, xinc1, xinc2; | ||
285 | int y, yinc1, yinc2; | ||
286 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; | ||
287 | |||
288 | deltay = abs(y2 - y1); | ||
289 | if (deltay == 0) | ||
290 | { | ||
291 | /* DEBUGF("lcd_drawline() called for horizontal line - optimisation.\n"); */ | ||
292 | lcd_hline(x1, x2, y1); | ||
293 | return; | ||
294 | } | ||
295 | deltax = abs(x2 - x1); | ||
296 | if (deltax == 0) | ||
297 | { | ||
298 | /* DEBUGF("lcd_drawline() called for vertical line - optimisation.\n"); */ | ||
299 | lcd_vline(x1, y1, y2); | ||
300 | return; | ||
301 | } | ||
302 | xinc2 = 1; | ||
303 | yinc2 = 1; | ||
304 | |||
305 | if (deltax >= deltay) | ||
306 | { | ||
307 | numpixels = deltax; | ||
308 | d = 2 * deltay - deltax; | ||
309 | dinc1 = deltay * 2; | ||
310 | dinc2 = (deltay - deltax) * 2; | ||
311 | xinc1 = 1; | ||
312 | yinc1 = 0; | ||
313 | } | ||
314 | else | ||
315 | { | ||
316 | numpixels = deltay; | ||
317 | d = 2 * deltax - deltay; | ||
318 | dinc1 = deltax * 2; | ||
319 | dinc2 = (deltax - deltay) * 2; | ||
320 | xinc1 = 0; | ||
321 | yinc1 = 1; | ||
322 | } | ||
323 | numpixels++; /* include endpoints */ | ||
324 | |||
325 | if (x1 > x2) | ||
326 | { | ||
327 | xinc1 = -xinc1; | ||
328 | xinc2 = -xinc2; | ||
329 | } | ||
330 | |||
331 | if (y1 > y2) | ||
332 | { | ||
333 | yinc1 = -yinc1; | ||
334 | yinc2 = -yinc2; | ||
335 | } | ||
336 | |||
337 | x = x1; | ||
338 | y = y1; | ||
339 | |||
340 | for (i = 0; i < numpixels; i++) | ||
341 | { | ||
342 | if ( ((unsigned)x < (unsigned)current_vp->width) | ||
343 | && ((unsigned)y < (unsigned)current_vp->height) | ||
344 | #if defined(HAVE_VIEWPORT_CLIP) | ||
345 | && ((unsigned)x < (unsigned)LCD_WIDTH) | ||
346 | && ((unsigned)y < (unsigned)LCD_HEIGHT) | ||
347 | #endif | ||
348 | ) | ||
349 | pfunc(LCDADDR(x + current_vp->x, y + current_vp->y)); | ||
350 | |||
351 | if (d < 0) | ||
352 | { | ||
353 | d += dinc1; | ||
354 | x += xinc1; | ||
355 | y += yinc1; | ||
356 | } | ||
357 | else | ||
358 | { | ||
359 | d += dinc2; | ||
360 | x += xinc2; | ||
361 | y += yinc2; | ||
362 | } | ||
363 | } | ||
364 | } | ||
365 | |||
366 | /* Draw a rectangular box */ | ||
367 | void lcd_drawrect(int x, int y, int width, int height) | ||
368 | { | ||
369 | if ((width <= 0) || (height <= 0)) | ||
370 | return; | ||
371 | |||
372 | int x2 = x + width - 1; | ||
373 | int y2 = y + height - 1; | ||
374 | |||
375 | lcd_vline(x, y, y2); | ||
376 | lcd_vline(x2, y, y2); | ||
377 | lcd_hline(x, x2, y); | ||
378 | lcd_hline(x, x2, y2); | ||
379 | } | ||
380 | |||
381 | |||
31 | /* About Rockbox' internal monochrome bitmap format: | 382 | /* About Rockbox' internal monochrome bitmap format: |
32 | * | 383 | * |
33 | * A bitmap contains one bit for every pixel that defines if that pixel is | 384 | * A bitmap contains one bit for every pixel that defines if that pixel is |
@@ -54,7 +405,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
54 | 405 | ||
55 | /******************** Image in viewport clipping **********************/ | 406 | /******************** Image in viewport clipping **********************/ |
56 | /* nothing to draw? */ | 407 | /* nothing to draw? */ |
57 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 408 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
58 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 409 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
59 | return; | 410 | return; |
60 | 411 | ||
@@ -74,18 +425,18 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
74 | width = current_vp->width - x; | 425 | width = current_vp->width - x; |
75 | if (y + height > current_vp->height) | 426 | if (y + height > current_vp->height) |
76 | height = current_vp->height - y; | 427 | height = current_vp->height - y; |
77 | 428 | ||
78 | /* adjust for viewport */ | 429 | /* adjust for viewport */ |
79 | x += current_vp->x; | 430 | x += current_vp->x; |
80 | y += current_vp->y; | 431 | y += current_vp->y; |
81 | 432 | ||
82 | #if defined(HAVE_VIEWPORT_CLIP) | 433 | #if defined(HAVE_VIEWPORT_CLIP) |
83 | /********************* Viewport on screen clipping ********************/ | 434 | /********************* Viewport on screen clipping ********************/ |
84 | /* nothing to draw? */ | 435 | /* nothing to draw? */ |
85 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 436 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
86 | || (x + width <= 0) || (y + height <= 0)) | 437 | || (x + width <= 0) || (y + height <= 0)) |
87 | return; | 438 | return; |
88 | 439 | ||
89 | /* clip image in viewport in screen */ | 440 | /* clip image in viewport in screen */ |
90 | if (x < 0) | 441 | if (x < 0) |
91 | { | 442 | { |
@@ -109,7 +460,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
109 | src_y &= 7; | 460 | src_y &= 7; |
110 | src_end = src + width; | 461 | src_end = src + width; |
111 | dst_col = LCDADDR(x, y); | 462 | dst_col = LCDADDR(x, y); |
112 | 463 | ||
113 | 464 | ||
114 | if (drmode & DRMODE_INVERSEVID) | 465 | if (drmode & DRMODE_INVERSEVID) |
115 | { | 466 | { |
@@ -200,7 +551,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
200 | bo = lcd_backdrop_offset; | 551 | bo = lcd_backdrop_offset; |
201 | do | 552 | do |
202 | { | 553 | { |
203 | *dst = (data & 0x01) ? fg | 554 | *dst = (data & 0x01) ? fg |
204 | : *(fb_data *)((long)dst + bo); | 555 | : *(fb_data *)((long)dst + bo); |
205 | dst += ROW_INC; | 556 | dst += ROW_INC; |
206 | UPDATE_SRC; | 557 | UPDATE_SRC; |
@@ -348,10 +699,10 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
348 | #if defined(HAVE_VIEWPORT_CLIP) | 699 | #if defined(HAVE_VIEWPORT_CLIP) |
349 | /********************* Viewport on screen clipping ********************/ | 700 | /********************* Viewport on screen clipping ********************/ |
350 | /* nothing to draw? */ | 701 | /* nothing to draw? */ |
351 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 702 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
352 | || (x + width <= 0) || (y + height <= 0)) | 703 | || (x + width <= 0) || (y + height <= 0)) |
353 | return; | 704 | return; |
354 | 705 | ||
355 | /* clip image in viewport in screen */ | 706 | /* clip image in viewport in screen */ |
356 | if (x < 0) | 707 | if (x < 0) |
357 | { | 708 | { |