diff options
author | Jens Arnold <amiconn@rockbox.org> | 2009-03-08 17:22:17 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2009-03-08 17:22:17 +0000 |
commit | 9eeead922ad958cae62015eec8156e47ca47fc58 (patch) | |
tree | f920b48878aae27cf77f301396eb811d9e8a187a /firmware | |
parent | 87d1744e91e016b650a3c7826a93cd6afcaf0383 (diff) | |
download | rockbox-9eeead922ad958cae62015eec8156e47ca47fc58.tar.gz rockbox-9eeead922ad958cae62015eec8156e47ca47fc58.zip |
Optimize hline, fillrect and mono bitmap drawing for chunky displays (16 bit colour and greylib). Speeds up text rendering by 20..45% on colour coldfire, by 30..50% on colour ARM, and is noticeable in archos pictureflow.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20242 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 193 |
1 files changed, 140 insertions, 53 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index 9b700a0669..c3e076b392 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -428,7 +428,6 @@ void lcd_hline(int x1, int x2, int y) | |||
428 | unsigned bits = 0; | 428 | unsigned bits = 0; |
429 | enum fill_opt fillopt = OPT_NONE; | 429 | enum fill_opt fillopt = OPT_NONE; |
430 | fb_data *dst, *dst_end; | 430 | fb_data *dst, *dst_end; |
431 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; | ||
432 | 431 | ||
433 | /* direction flip */ | 432 | /* direction flip */ |
434 | if (x2 < x1) | 433 | if (x2 < x1) |
@@ -444,18 +443,7 @@ void lcd_hline(int x1, int x2, int y) | |||
444 | (x2 < 0)) | 443 | (x2 < 0)) |
445 | return; | 444 | return; |
446 | 445 | ||
447 | /* clipping */ | 446 | /* drawmode and optimisation */ |
448 | if (x1 < 0) | ||
449 | x1 = 0; | ||
450 | if (x2 >= current_vp->width) | ||
451 | x2 = current_vp->width-1; | ||
452 | |||
453 | width = x2 - x1 + 1; | ||
454 | |||
455 | /* Adjust x1 and y to viewport */ | ||
456 | x1 += current_vp->x; | ||
457 | y += current_vp->y; | ||
458 | |||
459 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 447 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
460 | { | 448 | { |
461 | if (current_vp->drawmode & DRMODE_BG) | 449 | if (current_vp->drawmode & DRMODE_BG) |
@@ -477,6 +465,21 @@ void lcd_hline(int x1, int x2, int y) | |||
477 | bits = current_vp->fg_pattern; | 465 | bits = current_vp->fg_pattern; |
478 | } | 466 | } |
479 | } | 467 | } |
468 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) | ||
469 | return; | ||
470 | |||
471 | /* clipping */ | ||
472 | if (x1 < 0) | ||
473 | x1 = 0; | ||
474 | if (x2 >= current_vp->width) | ||
475 | x2 = current_vp->width-1; | ||
476 | |||
477 | width = x2 - x1 + 1; | ||
478 | |||
479 | /* Adjust x1 and y to viewport */ | ||
480 | x1 += current_vp->x; | ||
481 | y += current_vp->y; | ||
482 | |||
480 | dst = LCDADDR(x1, y); | 483 | dst = LCDADDR(x1, y); |
481 | 484 | ||
482 | switch (fillopt) | 485 | switch (fillopt) |
@@ -490,11 +493,11 @@ void lcd_hline(int x1, int x2, int y) | |||
490 | width * sizeof(fb_data)); | 493 | width * sizeof(fb_data)); |
491 | break; | 494 | break; |
492 | 495 | ||
493 | case OPT_NONE: | 496 | case OPT_NONE: /* DRMODE_COMPLEMENT */ |
494 | dst_end = dst + width; | 497 | dst_end = dst + width; |
495 | do | 498 | do |
496 | pfunc(dst++); | 499 | *dst = ~(*dst); |
497 | while (dst < dst_end); | 500 | while (++dst < dst_end); |
498 | break; | 501 | break; |
499 | } | 502 | } |
500 | } | 503 | } |
@@ -558,29 +561,13 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
558 | unsigned bits = 0; | 561 | unsigned bits = 0; |
559 | enum fill_opt fillopt = OPT_NONE; | 562 | enum fill_opt fillopt = OPT_NONE; |
560 | fb_data *dst, *dst_end; | 563 | fb_data *dst, *dst_end; |
561 | lcd_fastpixelfunc_type *pfunc = lcd_fastpixelfuncs[current_vp->drawmode]; | ||
562 | 564 | ||
563 | /* nothing to draw? */ | 565 | /* nothing to draw? */ |
564 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 566 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
565 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | 567 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) |
566 | return; | 568 | return; |
567 | 569 | ||
568 | /* clipping */ | 570 | /* drawmode and optimisation */ |
569 | if (x < 0) | ||
570 | { | ||
571 | width += x; | ||
572 | x = 0; | ||
573 | } | ||
574 | if (y < 0) | ||
575 | { | ||
576 | height += y; | ||
577 | y = 0; | ||
578 | } | ||
579 | if (x + width > current_vp->width) | ||
580 | width = current_vp->width - x; | ||
581 | if (y + height > current_vp->height) | ||
582 | height = current_vp->height - y; | ||
583 | |||
584 | if (current_vp->drawmode & DRMODE_INVERSEVID) | 571 | if (current_vp->drawmode & DRMODE_INVERSEVID) |
585 | { | 572 | { |
586 | if (current_vp->drawmode & DRMODE_BG) | 573 | if (current_vp->drawmode & DRMODE_BG) |
@@ -602,6 +589,25 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
602 | bits = current_vp->fg_pattern; | 589 | bits = current_vp->fg_pattern; |
603 | } | 590 | } |
604 | } | 591 | } |
592 | if (fillopt == OPT_NONE && current_vp->drawmode != DRMODE_COMPLEMENT) | ||
593 | return; | ||
594 | |||
595 | /* clipping */ | ||
596 | if (x < 0) | ||
597 | { | ||
598 | width += x; | ||
599 | x = 0; | ||
600 | } | ||
601 | if (y < 0) | ||
602 | { | ||
603 | height += y; | ||
604 | y = 0; | ||
605 | } | ||
606 | if (x + width > current_vp->width) | ||
607 | width = current_vp->width - x; | ||
608 | if (y + height > current_vp->height) | ||
609 | height = current_vp->height - y; | ||
610 | |||
605 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 611 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); |
606 | dst_end = dst + height * LCD_WIDTH; | 612 | dst_end = dst + height * LCD_WIDTH; |
607 | 613 | ||
@@ -620,12 +626,12 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
620 | width * sizeof(fb_data)); | 626 | width * sizeof(fb_data)); |
621 | break; | 627 | break; |
622 | 628 | ||
623 | case OPT_NONE: | 629 | case OPT_NONE: /* DRMODE_COMPLEMENT */ |
624 | dst_row = dst; | 630 | dst_row = dst; |
625 | row_end = dst_row + width; | 631 | row_end = dst_row + width; |
626 | do | 632 | do |
627 | pfunc(dst_row++); | 633 | *dst_row = ~(*dst_row); |
628 | while (dst_row < row_end); | 634 | while (++dst_row < row_end); |
629 | break; | 635 | break; |
630 | } | 636 | } |
631 | dst += LCD_WIDTH; | 637 | dst += LCD_WIDTH; |
@@ -717,7 +723,8 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
717 | { | 723 | { |
718 | const unsigned char *src_end; | 724 | const unsigned char *src_end; |
719 | fb_data *dst, *dst_end; | 725 | fb_data *dst, *dst_end; |
720 | lcd_fastpixelfunc_type *fgfunc, *bgfunc; | 726 | unsigned dmask = 0x100; /* bit 8 == sentinel */ |
727 | int drmode = current_vp->drawmode; | ||
721 | 728 | ||
722 | /* nothing to draw? */ | 729 | /* nothing to draw? */ |
723 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 730 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || |
@@ -745,35 +752,115 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
745 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | 752 | src += stride * (src_y >> 3) + src_x; /* move starting point */ |
746 | src_y &= 7; | 753 | src_y &= 7; |
747 | src_end = src + width; | 754 | src_end = src + width; |
748 | |||
749 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 755 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); |
750 | fgfunc = lcd_fastpixelfuncs[current_vp->drawmode]; | 756 | |
751 | bgfunc = lcd_fastpixelfuncs[current_vp->drawmode ^ DRMODE_INVERSEVID]; | 757 | if (drmode & DRMODE_INVERSEVID) |
758 | { | ||
759 | dmask = 0x1ff; /* bit 8 == sentinel */ | ||
760 | drmode &= DRMODE_SOLID; /* mask out inversevid */ | ||
761 | } | ||
762 | |||
752 | do | 763 | do |
753 | { | 764 | { |
754 | const unsigned char *src_col = src++; | 765 | const unsigned char *src_col = src++; |
755 | unsigned data = *src_col >> src_y; | 766 | unsigned data = (*src_col ^ dmask) >> src_y; |
756 | fb_data *dst_col = dst++; | 767 | fb_data *dst_col = dst++; |
757 | int numbits = 8 - src_y; | 768 | int fg, bg; |
769 | long bo; | ||
770 | |||
758 | dst_end = dst_col + height * LCD_WIDTH; | 771 | dst_end = dst_col + height * LCD_WIDTH; |
759 | do | 772 | |
773 | #define UPDATE_SRC do { \ | ||
774 | data >>= 1; \ | ||
775 | if (data == 0x001) { \ | ||
776 | src_col += stride; \ | ||
777 | data = *src_col ^ dmask; \ | ||
778 | } \ | ||
779 | } while (0) | ||
780 | |||
781 | switch (drmode) | ||
760 | { | 782 | { |
761 | if (data & 0x01) | 783 | case DRMODE_COMPLEMENT: |
762 | fgfunc(dst_col); | 784 | do |
785 | { | ||
786 | if (data & 0x01) | ||
787 | *dst_col = ~(*dst_col); | ||
788 | |||
789 | dst_col += LCD_WIDTH; | ||
790 | UPDATE_SRC; | ||
791 | } | ||
792 | while (dst_col < dst_end); | ||
793 | break; | ||
794 | |||
795 | case DRMODE_BG: | ||
796 | if (lcd_backdrop) | ||
797 | { | ||
798 | bo = lcd_backdrop_offset; | ||
799 | do | ||
800 | { | ||
801 | if (!(data & 0x01)) | ||
802 | *dst_col = *(fb_data *)((long)dst_col + bo); | ||
803 | |||
804 | dst_col += LCD_WIDTH; | ||
805 | UPDATE_SRC; | ||
806 | } | ||
807 | while (dst_col < dst_end); | ||
808 | } | ||
763 | else | 809 | else |
764 | bgfunc(dst_col); | 810 | { |
811 | bg = current_vp->bg_pattern; | ||
812 | do | ||
813 | { | ||
814 | if (!(data & 0x01)) | ||
815 | *dst_col = bg; | ||
816 | |||
817 | dst_col += LCD_WIDTH; | ||
818 | UPDATE_SRC; | ||
819 | } | ||
820 | while (dst_col < dst_end); | ||
821 | } | ||
822 | break; | ||
765 | 823 | ||
766 | dst_col += LCD_WIDTH; | 824 | case DRMODE_FG: |
825 | fg = current_vp->fg_pattern; | ||
826 | do | ||
827 | { | ||
828 | if (data & 0x01) | ||
829 | *dst_col = fg; | ||
767 | 830 | ||
768 | data >>= 1; | 831 | dst_col += LCD_WIDTH; |
769 | if (--numbits == 0) | 832 | UPDATE_SRC; |
833 | } | ||
834 | while (dst_col < dst_end); | ||
835 | break; | ||
836 | |||
837 | case DRMODE_SOLID: | ||
838 | fg = current_vp->fg_pattern; | ||
839 | if (lcd_backdrop) | ||
770 | { | 840 | { |
771 | src_col += stride; | 841 | bo = lcd_backdrop_offset; |
772 | data = *src_col; | 842 | do |
773 | numbits = 8; | 843 | { |
844 | *dst_col = (data & 0x01) ? fg | ||
845 | : *(fb_data *)((long)dst_col + bo); | ||
846 | dst_col += LCD_WIDTH; | ||
847 | UPDATE_SRC; | ||
848 | } | ||
849 | while (dst_col < dst_end); | ||
774 | } | 850 | } |
851 | else | ||
852 | { | ||
853 | bg = current_vp->bg_pattern; | ||
854 | do | ||
855 | { | ||
856 | *dst_col = (data & 0x01) ? fg : bg; | ||
857 | dst_col += LCD_WIDTH; | ||
858 | UPDATE_SRC; | ||
859 | } | ||
860 | while (dst_col < dst_end); | ||
861 | } | ||
862 | break; | ||
775 | } | 863 | } |
776 | while (dst_col < dst_end); | ||
777 | } | 864 | } |
778 | while (src < src_end); | 865 | while (src < src_end); |
779 | } | 866 | } |