diff options
author | Linus Nielsen Feltzing <linus@haxx.se> | 2005-11-14 20:48:34 +0000 |
---|---|---|
committer | Linus Nielsen Feltzing <linus@haxx.se> | 2005-11-14 20:48:34 +0000 |
commit | 63dc8c14b03d6fb3a2e8193fd2d976563496b9e5 (patch) | |
tree | f090900d60101bc27575b45ec10addf532ea551a | |
parent | f1bdfbf691fcde8e6b635cb62abf3c7269dc7255 (diff) | |
download | rockbox-63dc8c14b03d6fb3a2e8193fd2d976563496b9e5.tar.gz rockbox-63dc8c14b03d6fb3a2e8193fd2d976563496b9e5.zip |
The 16-bit LCD driver is now 16-bit for real
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7880 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 305 |
1 files changed, 39 insertions, 266 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 933d02e64a..9e2bf11446 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -34,13 +34,13 @@ | |||
34 | 34 | ||
35 | #define SCROLLABLE_LINES 26 | 35 | #define SCROLLABLE_LINES 26 |
36 | 36 | ||
37 | #define RGB_PACK(r,g,b) (swap16(((r>>3)<<11)|((g>>2)<<5)|(b>>3))) | 37 | #define RGB_PACK(r,g,b) (htobe16(((r>>3)<<11)|((g>>2)<<5)|(b>>3))) |
38 | 38 | ||
39 | /*** globals ***/ | 39 | /*** globals ***/ |
40 | unsigned char lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH*2] __attribute__ ((aligned (2))); | 40 | fb_data lcd_framebuffer[LCD_HEIGHT][LCD_WIDTH] __attribute__ ((aligned (2))); |
41 | 41 | ||
42 | static unsigned fg_pattern = 0x0000; /* Black */ | 42 | static unsigned fg_pattern = 0x0000; /* Black */ |
43 | static unsigned bg_pattern = 0xbc2d; /* "Rockbox blue" */ | 43 | static unsigned bg_pattern = RGB_PACK(0xb6, 0xc6, 0xe5); /* "Rockbox blue" */ |
44 | static int drawmode = DRMODE_SOLID; | 44 | static int drawmode = DRMODE_SOLID; |
45 | static int xmargin = 0; | 45 | static int xmargin = 0; |
46 | static int ymargin = 0; | 46 | static int ymargin = 0; |
@@ -155,14 +155,12 @@ int lcd_getstringsize(const unsigned char *str, int *w, int *h) | |||
155 | 155 | ||
156 | static void setpixel(int x, int y) | 156 | static void setpixel(int x, int y) |
157 | { | 157 | { |
158 | unsigned short *data = (unsigned short*)&lcd_framebuffer[y][x*2]; | 158 | lcd_framebuffer[y][x] = fg_pattern; |
159 | *data = fg_pattern; | ||
160 | } | 159 | } |
161 | 160 | ||
162 | static void clearpixel(int x, int y) | 161 | static void clearpixel(int x, int y) |
163 | { | 162 | { |
164 | unsigned short *data = (unsigned short*)&lcd_framebuffer[y][x*2]; | 163 | lcd_framebuffer[y][x] = bg_pattern; |
165 | *data = bg_pattern; | ||
166 | } | 164 | } |
167 | 165 | ||
168 | static void flippixel(int x, int y) | 166 | static void flippixel(int x, int y) |
@@ -184,82 +182,6 @@ lcd_pixelfunc_type* const lcd_pixelfuncs[8] = { | |||
184 | nopixel, clearpixel, nopixel, clearpixel | 182 | nopixel, clearpixel, nopixel, clearpixel |
185 | }; | 183 | }; |
186 | 184 | ||
187 | /* 'mask' and 'bits' contain 2 bits per pixel */ | ||
188 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) | ||
189 | ICODE_ATTR; | ||
190 | static void flipblock(unsigned char *address, unsigned mask, unsigned bits) | ||
191 | { | ||
192 | *address ^= bits & mask; | ||
193 | } | ||
194 | |||
195 | static void bgblock(unsigned char *address, unsigned mask, unsigned bits) | ||
196 | ICODE_ATTR; | ||
197 | static void bgblock(unsigned char *address, unsigned mask, unsigned bits) | ||
198 | { | ||
199 | (void)bits; | ||
200 | if (mask > 0) { | ||
201 | *address = bg_pattern; | ||
202 | } else { | ||
203 | *address = fg_pattern; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static void fgblock(unsigned char *address, unsigned mask, unsigned bits) | ||
208 | ICODE_ATTR; | ||
209 | static void fgblock(unsigned char *address, unsigned mask, unsigned bits) | ||
210 | { | ||
211 | (void)bits; | ||
212 | if (mask > 0) { | ||
213 | *address = fg_pattern; | ||
214 | } else { | ||
215 | *address = bg_pattern; | ||
216 | } | ||
217 | } | ||
218 | |||
219 | static void solidblock(unsigned char *address, unsigned mask, unsigned bits) | ||
220 | ICODE_ATTR; | ||
221 | static void solidblock(unsigned char *address, unsigned mask, unsigned bits) | ||
222 | { | ||
223 | *address = (*address & ~mask) | (bits & mask & fg_pattern) | ||
224 | | (~bits & mask & bg_pattern); | ||
225 | } | ||
226 | |||
227 | static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
228 | ICODE_ATTR; | ||
229 | static void flipinvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
230 | { | ||
231 | *address ^= ~bits & mask; | ||
232 | } | ||
233 | |||
234 | static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
235 | ICODE_ATTR; | ||
236 | static void bginvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
237 | { | ||
238 | mask &= bits; | ||
239 | *address = (*address & ~mask) | (bg_pattern & mask); | ||
240 | } | ||
241 | |||
242 | static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
243 | ICODE_ATTR; | ||
244 | static void fginvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
245 | { | ||
246 | mask &= ~bits; | ||
247 | *address = (*address & ~mask) | (fg_pattern & mask); | ||
248 | } | ||
249 | |||
250 | static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
251 | ICODE_ATTR; | ||
252 | static void solidinvblock(unsigned char *address, unsigned mask, unsigned bits) | ||
253 | { | ||
254 | *address = (*address & ~mask) | (~bits & mask & fg_pattern) | ||
255 | | (bits & mask & bg_pattern); | ||
256 | } | ||
257 | |||
258 | lcd_blockfunc_type* const lcd_blockfuncs[8] = { | ||
259 | flipblock, bgblock, fgblock, solidblock, | ||
260 | flipinvblock, bginvblock, fginvblock, solidinvblock | ||
261 | }; | ||
262 | |||
263 | /*** drawing functions ***/ | 185 | /*** drawing functions ***/ |
264 | 186 | ||
265 | /* Clear the whole display */ | 187 | /* Clear the whole display */ |
@@ -267,7 +189,7 @@ void lcd_clear_display(void) | |||
267 | { | 189 | { |
268 | int i; | 190 | int i; |
269 | unsigned short bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; | 191 | unsigned short bits = (drawmode & DRMODE_INVERSEVID) ? fg_pattern : bg_pattern; |
270 | unsigned short* addr = (unsigned short*)lcd_framebuffer; | 192 | unsigned short* addr = (unsigned short *)lcd_framebuffer; |
271 | 193 | ||
272 | for (i=0;i<LCD_HEIGHT*LCD_WIDTH;i++) { | 194 | for (i=0;i<LCD_HEIGHT*LCD_WIDTH;i++) { |
273 | *(addr++)=bits; | 195 | *(addr++)=bits; |
@@ -357,9 +279,7 @@ void lcd_drawline(int x1, int y1, int x2, int y2) | |||
357 | void lcd_hline(int x1, int x2, int y) | 279 | void lcd_hline(int x1, int x2, int y) |
358 | { | 280 | { |
359 | int x; | 281 | int x; |
360 | unsigned char *dst, *dst_end; | 282 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; |
361 | unsigned mask; | ||
362 | lcd_blockfunc_type *bfunc; | ||
363 | 283 | ||
364 | /* direction flip */ | 284 | /* direction flip */ |
365 | if (x2 < x1) | 285 | if (x2 < x1) |
@@ -379,30 +299,23 @@ void lcd_hline(int x1, int x2, int y) | |||
379 | if (x2 >= LCD_WIDTH) | 299 | if (x2 >= LCD_WIDTH) |
380 | x2 = LCD_WIDTH-1; | 300 | x2 = LCD_WIDTH-1; |
381 | 301 | ||
382 | bfunc = lcd_blockfuncs[drawmode]; | ||
383 | dst = &lcd_framebuffer[y>>2][x1]; | ||
384 | mask = 3 << (2 * (y & 3)); | ||
385 | |||
386 | dst_end = dst + x2 - x1; | ||
387 | do | 302 | do |
388 | bfunc(dst++, mask, 0xFFu); | 303 | pfunc(x1++, y); |
389 | while (dst <= dst_end); | 304 | while (x1 <= x2); |
390 | } | 305 | } |
391 | 306 | ||
392 | /* Draw a vertical line (optimised) */ | 307 | /* Draw a vertical line (optimised) */ |
393 | void lcd_vline(int x, int y1, int y2) | 308 | void lcd_vline(int x, int y1, int y2) |
394 | { | 309 | { |
395 | int ny; | 310 | int y; |
396 | unsigned char *dst; | 311 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; |
397 | unsigned mask, mask_bottom; | ||
398 | lcd_blockfunc_type *bfunc; | ||
399 | 312 | ||
400 | /* direction flip */ | 313 | /* direction flip */ |
401 | if (y2 < y1) | 314 | if (y2 < y1) |
402 | { | 315 | { |
403 | ny = y1; | 316 | y = y1; |
404 | y1 = y2; | 317 | y1 = y2; |
405 | y2 = ny; | 318 | y2 = y; |
406 | } | 319 | } |
407 | 320 | ||
408 | /* nothing to draw? */ | 321 | /* nothing to draw? */ |
@@ -415,20 +328,10 @@ void lcd_vline(int x, int y1, int y2) | |||
415 | if (y2 >= LCD_HEIGHT) | 328 | if (y2 >= LCD_HEIGHT) |
416 | y2 = LCD_HEIGHT-1; | 329 | y2 = LCD_HEIGHT-1; |
417 | 330 | ||
418 | bfunc = lcd_blockfuncs[drawmode]; | ||
419 | dst = &lcd_framebuffer[y1>>2][x]; | ||
420 | ny = y2 - (y1 & ~3); | ||
421 | mask = 0xFFu << (2 * (y1 & 3)); | ||
422 | mask_bottom = 0xFFu >> (2 * (~ny & 3)); | ||
423 | 331 | ||
424 | for (; ny >= 4; ny -= 4) | 332 | do |
425 | { | 333 | pfunc(x, y1++); |
426 | bfunc(dst, mask, 0xFFu); | 334 | while (y1 <= y2); |
427 | dst += LCD_WIDTH; | ||
428 | mask = 0xFFu; | ||
429 | } | ||
430 | mask &= mask_bottom; | ||
431 | bfunc(dst, mask, 0xFFu); | ||
432 | } | 335 | } |
433 | 336 | ||
434 | /* Draw a rectangular box */ | 337 | /* Draw a rectangular box */ |
@@ -449,12 +352,8 @@ void lcd_drawrect(int x, int y, int width, int height) | |||
449 | /* Fill a rectangular area */ | 352 | /* Fill a rectangular area */ |
450 | void lcd_fillrect(int x, int y, int width, int height) | 353 | void lcd_fillrect(int x, int y, int width, int height) |
451 | { | 354 | { |
452 | int ny; | 355 | int nx, ny; |
453 | unsigned char *dst, *dst_end; | 356 | lcd_pixelfunc_type *pfunc = lcd_pixelfuncs[drawmode]; |
454 | unsigned mask, mask_bottom; | ||
455 | unsigned bits = fg_pattern; | ||
456 | lcd_blockfunc_type *bfunc; | ||
457 | bool fillopt; | ||
458 | 357 | ||
459 | /* nothing to draw? */ | 358 | /* nothing to draw? */ |
460 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 359 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) |
@@ -476,44 +375,14 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
476 | width = LCD_WIDTH - x; | 375 | width = LCD_WIDTH - x; |
477 | if (y + height > LCD_HEIGHT) | 376 | if (y + height > LCD_HEIGHT) |
478 | height = LCD_HEIGHT - y; | 377 | height = LCD_HEIGHT - y; |
479 | |||
480 | fillopt = (drawmode & DRMODE_INVERSEVID) ? | ||
481 | (drawmode & DRMODE_BG) : (drawmode & DRMODE_FG); | ||
482 | if (fillopt &&(drawmode & DRMODE_INVERSEVID)) | ||
483 | bits = bg_pattern; | ||
484 | bfunc = lcd_blockfuncs[drawmode]; | ||
485 | dst = &lcd_framebuffer[y>>2][x]; | ||
486 | ny = height - 1 + (y & 3); | ||
487 | mask = 0xFFu << (2 * (y & 3)); | ||
488 | mask_bottom = 0xFFu >> (2 * (~ny & 3)); | ||
489 | |||
490 | for (; ny >= 4; ny -= 4) | ||
491 | { | ||
492 | if (fillopt && (mask == 0xFFu)) | ||
493 | memset(dst, bits, width); | ||
494 | else | ||
495 | { | ||
496 | unsigned char *dst_row = dst; | ||
497 | |||
498 | dst_end = dst_row + width; | ||
499 | do | ||
500 | bfunc(dst_row++, mask, 0xFFu); | ||
501 | while (dst_row < dst_end); | ||
502 | } | ||
503 | |||
504 | dst += LCD_WIDTH; | ||
505 | mask = 0xFFu; | ||
506 | } | ||
507 | mask &= mask_bottom; | ||
508 | 378 | ||
509 | if (fillopt && (mask == 0xFFu)) | 379 | ny = y + height; |
510 | memset(dst, bits, width); | 380 | for(;y < ny;y++) |
511 | else | ||
512 | { | 381 | { |
513 | dst_end = dst + width; | 382 | int xc; |
514 | do | 383 | nx = x + width; |
515 | bfunc(dst++, mask, 0xFFu); | 384 | for(xc = x;xc < nx;xc++) |
516 | while (dst < dst_end); | 385 | pfunc(x, y); |
517 | } | 386 | } |
518 | } | 387 | } |
519 | 388 | ||
@@ -541,7 +410,7 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
541 | int out_x; | 410 | int out_x; |
542 | int out_y; | 411 | int out_y; |
543 | unsigned char pixel; | 412 | unsigned char pixel; |
544 | unsigned short* addr; | 413 | fb_data * addr; |
545 | 414 | ||
546 | (void)stride; | 415 | (void)stride; |
547 | /* nothing to draw? */ | 416 | /* nothing to draw? */ |
@@ -575,7 +444,7 @@ void lcd_mono_bitmap_part(const unsigned char *src, int src_x, int src_y, | |||
575 | in_y=src_y; | 444 | in_y=src_y; |
576 | for (out_y=y;out_y<(y+height);out_y++) { | 445 | for (out_y=y;out_y<(y+height);out_y++) { |
577 | pixel=(*src)&masks[in_y]; | 446 | pixel=(*src)&masks[in_y]; |
578 | addr=(unsigned short*)&lcd_framebuffer[out_y][out_x*2]; | 447 | addr=&lcd_framebuffer[out_y][out_x]; |
579 | if (pixel > 0) { | 448 | if (pixel > 0) { |
580 | *addr=fg_pattern; | 449 | *addr=fg_pattern; |
581 | } else { | 450 | } else { |
@@ -595,123 +464,27 @@ void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int heig | |||
595 | } | 464 | } |
596 | 465 | ||
597 | /* Draw a partial native bitmap */ | 466 | /* Draw a partial native bitmap */ |
598 | void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, | 467 | void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, |
599 | int stride, int x, int y, int width, int height) | 468 | int stride, int x, int y, int width, int height) |
600 | ICODE_ATTR; | 469 | ICODE_ATTR; |
601 | void lcd_bitmap_part(const unsigned char *src, int src_x, int src_y, | 470 | void lcd_bitmap_part(const fb_data *src, int src_x, int src_y, |
602 | int stride, int x, int y, int width, int height) | 471 | int stride, int x, int y, int width, int height) |
603 | { | 472 | { |
604 | int shift, ny; | 473 | (void)src; |
605 | unsigned char *dst, *dst_end; | 474 | (void)src_x; |
606 | unsigned mask, mask_bottom; | 475 | (void)src_y; |
607 | lcd_blockfunc_type *bfunc; | 476 | (void)stride; |
608 | 477 | (void)x; | |
609 | /* nothing to draw? */ | 478 | (void)y; |
610 | if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | 479 | (void)width; |
611 | || (x + width <= 0) || (y + height <= 0)) | 480 | (void)height; |
612 | return; | ||
613 | |||
614 | /* clipping */ | ||
615 | if (x < 0) | ||
616 | { | ||
617 | width += x; | ||
618 | src_x -= x; | ||
619 | x = 0; | ||
620 | } | ||
621 | if (y < 0) | ||
622 | { | ||
623 | height += y; | ||
624 | src_y -= y; | ||
625 | y = 0; | ||
626 | } | ||
627 | if (x + width > LCD_WIDTH) | ||
628 | width = LCD_WIDTH - x; | ||
629 | if (y + height > LCD_HEIGHT) | ||
630 | height = LCD_HEIGHT - y; | ||
631 | |||
632 | src += stride * (src_y >> 2) + src_x; /* move starting point */ | ||
633 | src_y &= 3; | ||
634 | y -= src_y; | ||
635 | dst = &lcd_framebuffer[y>>2][x]; | ||
636 | shift = y & 3; | ||
637 | ny = height - 1 + shift + src_y; | ||
638 | |||
639 | bfunc = lcd_blockfuncs[drawmode]; | ||
640 | mask = 0xFFu << (2 * (shift + src_y)); | ||
641 | mask_bottom = 0xFFu >> (2 * (~ny & 3)); | ||
642 | |||
643 | if (shift == 0) | ||
644 | { | ||
645 | for (; ny >= 4; ny -= 4) | ||
646 | { | ||
647 | if (mask == 0xFFu) | ||
648 | memcpy(dst, src, width); | ||
649 | else | ||
650 | { | ||
651 | const unsigned char *src_row = src; | ||
652 | unsigned char *dst_row = dst; | ||
653 | |||
654 | dst_end = dst_row + width; | ||
655 | do | ||
656 | bfunc(dst_row++, mask, *src_row++); | ||
657 | while (dst_row < dst_end); | ||
658 | } | ||
659 | |||
660 | src += stride; | ||
661 | dst += LCD_WIDTH; | ||
662 | mask = 0xFFu; | ||
663 | } | ||
664 | mask &= mask_bottom; | ||
665 | |||
666 | if (mask == 0xFFu) | ||
667 | memcpy(dst, src, width); | ||
668 | else | ||
669 | { | ||
670 | dst_end = dst + width; | ||
671 | do | ||
672 | bfunc(dst++, mask, *src++); | ||
673 | while (dst < dst_end); | ||
674 | } | ||
675 | } | ||
676 | else | ||
677 | { | ||
678 | shift *= 2; | ||
679 | dst_end = dst + width; | ||
680 | do | ||
681 | { | ||
682 | const unsigned char *src_col = src++; | ||
683 | unsigned char *dst_col = dst++; | ||
684 | unsigned mask_col = mask; | ||
685 | unsigned data = 0; | ||
686 | |||
687 | for (y = ny; y >= 4; y -= 4) | ||
688 | { | ||
689 | data |= *src_col << shift; | ||
690 | |||
691 | if (mask_col & 0xFFu) | ||
692 | { | ||
693 | bfunc(dst_col, mask_col, data); | ||
694 | mask_col = 0xFFu; | ||
695 | } | ||
696 | else | ||
697 | mask_col >>= 8; | ||
698 | |||
699 | src_col += stride; | ||
700 | dst_col += LCD_WIDTH; | ||
701 | data >>= 8; | ||
702 | } | ||
703 | data |= *src_col << shift; | ||
704 | bfunc(dst_col, mask_col & mask_bottom, data); | ||
705 | } | ||
706 | while (dst < dst_end); | ||
707 | } | ||
708 | } | 481 | } |
709 | 482 | ||
710 | /* Draw a full native bitmap */ | 483 | /* Draw a full native bitmap */ |
711 | void lcd_bitmap(const unsigned char *src, int x, int y, int width, int height) | 484 | void lcd_bitmap(const fb_data *src, int x, int y, int width, int height) |
712 | { | 485 | { |
713 | unsigned short* s=(unsigned short*)src; | 486 | fb_data* s=(fb_data *)src; |
714 | unsigned short* d=(unsigned short*)&lcd_framebuffer[y][x*2]; | 487 | fb_data* d=&lcd_framebuffer[y][x]; |
715 | int k=LCD_WIDTH-width; | 488 | int k=LCD_WIDTH-width; |
716 | int i,j; | 489 | int i,j; |
717 | 490 | ||