diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 119 |
1 files changed, 80 insertions, 39 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index d1b417a00a..cee6c2aeef 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -788,34 +788,36 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
788 | int stride, int x, int y, int width, | 788 | int stride, int x, int y, int width, |
789 | int height) | 789 | int height) |
790 | { | 790 | { |
791 | fb_data *dst, *dst_end; | 791 | fb_data *dst; |
792 | 792 | ||
793 | /* nothing to draw? */ | 793 | if (x + width > current_vp->width) |
794 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 794 | width = current_vp->width - x; /* Clip right */ |
795 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
796 | return; | ||
797 | 795 | ||
798 | /* clipping */ | 796 | if (x < 0) /* Clip left */ |
799 | if (x < 0) | ||
800 | { | 797 | { |
801 | width += x; | 798 | width += x; |
802 | src_x -= x; | 799 | src_x -= x; |
803 | x = 0; | 800 | x = 0; |
804 | } | 801 | } |
805 | if (y < 0) | 802 | |
803 | if (width <= 0) | ||
804 | return; /* nothing left to do */ | ||
805 | |||
806 | if (y + height > current_vp->height) | ||
807 | height = current_vp->height - y; /* Clip bottom */ | ||
808 | |||
809 | if (y < 0) /* Clip top */ | ||
806 | { | 810 | { |
807 | height += y; | 811 | height += y; |
808 | src_y -= y; | 812 | src_y -= y; |
809 | y = 0; | 813 | y = 0; |
810 | } | 814 | } |
811 | if (x + width > current_vp->width) | 815 | |
812 | width = current_vp->width - x; | 816 | if (height <= 0) |
813 | if (y + height > current_vp->height) | 817 | return; /* nothing left to do */ |
814 | height = current_vp->height - y; | ||
815 | 818 | ||
816 | src += stride * src_y + src_x; /* move starting point */ | 819 | src += stride * src_y + src_x; /* move starting point */ |
817 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 820 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); |
818 | dst_end = dst + height * LCD_WIDTH; | ||
819 | 821 | ||
820 | do | 822 | do |
821 | { | 823 | { |
@@ -823,7 +825,7 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
823 | src += stride; | 825 | src += stride; |
824 | dst += LCD_WIDTH; | 826 | dst += LCD_WIDTH; |
825 | } | 827 | } |
826 | while (dst < dst_end); | 828 | while (--height > 0); |
827 | } | 829 | } |
828 | 830 | ||
829 | /* Draw a full native bitmap */ | 831 | /* Draw a full native bitmap */ |
@@ -832,60 +834,99 @@ void lcd_bitmap(const fb_data *src, int x, int y, int width, int height) | |||
832 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); | 834 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); |
833 | } | 835 | } |
834 | 836 | ||
835 | #if !defined(TOSHIBA_GIGABEAT_F) && !defined(TOSHIBA_GIGABEAT_S) \ | 837 | /* Draw a partial native bitmap with transparency and foreground colors */ |
836 | || defined(SIMULATOR) | ||
837 | /* Draw a partial native bitmap */ | ||
838 | void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, | 838 | void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, |
839 | int src_y, int stride, int x, | 839 | int src_y, int stride, int x, |
840 | int y, int width, int height) | 840 | int y, int width, int height) |
841 | { | 841 | { |
842 | fb_data *dst, *dst_end; | 842 | fb_data *dst; |
843 | unsigned fg = current_vp->fg_pattern; | ||
843 | 844 | ||
844 | /* nothing to draw? */ | 845 | if (x + width > current_vp->width) |
845 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 846 | width = current_vp->width - x; /* Clip right */ |
846 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
847 | return; | ||
848 | 847 | ||
849 | /* clipping */ | 848 | if (x < 0) /* Clip left */ |
850 | if (x < 0) | ||
851 | { | 849 | { |
852 | width += x; | 850 | width += x; |
853 | src_x -= x; | 851 | src_x -= x; |
854 | x = 0; | 852 | x = 0; |
855 | } | 853 | } |
856 | if (y < 0) | 854 | |
855 | if (width <= 0) | ||
856 | return; /* nothing left to do */ | ||
857 | |||
858 | if (y + height > current_vp->height) | ||
859 | height = current_vp->height - y; /* Clip bottom */ | ||
860 | |||
861 | if (y < 0) /* Clip top */ | ||
857 | { | 862 | { |
858 | height += y; | 863 | height += y; |
859 | src_y -= y; | 864 | src_y -= y; |
860 | y = 0; | 865 | y = 0; |
861 | } | 866 | } |
862 | if (x + width > current_vp->width) | 867 | |
863 | width = current_vp->width - x; | 868 | if (height <= 0) |
864 | if (y + height > current_vp->height) | 869 | return; /* nothing left to do */ |
865 | height = current_vp->height - y; | ||
866 | 870 | ||
867 | src += stride * src_y + src_x; /* move starting point */ | 871 | src += stride * src_y + src_x; /* move starting point */ |
868 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 872 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); |
869 | dst_end = dst + height * LCD_WIDTH; | ||
870 | 873 | ||
874 | #ifdef CPU_ARM | ||
875 | { | ||
876 | int w, px; | ||
877 | asm volatile ( | ||
878 | ".rowstart: \n" | ||
879 | "mov %[w], %[width] \n" /* Load width for inner loop */ | ||
880 | ".nextpixel: \n" | ||
881 | "ldrh %[px], [%[s]], #2 \n" /* Load src pixel */ | ||
882 | "add %[d], %[d], #2 \n" /* Uncoditionally increment dst */ | ||
883 | /* done here for better pipelining */ | ||
884 | "cmp %[px], %[fgcolor] \n" /* Compare to foreground color */ | ||
885 | "streqh %[fgpat], [%[d], #-2] \n" /* Store foregroud if match */ | ||
886 | "cmpne %[px], %[transcolor] \n" /* Compare to transparent color */ | ||
887 | "strneh %[px], [%[d], #-2] \n" /* Store dst if not transparent */ | ||
888 | "subs %[w], %[w], #1 \n" /* Width counter has run down? */ | ||
889 | "bgt .nextpixel \n" /* More in this row? */ | ||
890 | "add %[s], %[s], %[sstp], lsl #1 \n" /* Skip over to start of next line */ | ||
891 | "add %[d], %[d], %[dstp], lsl #1 \n" | ||
892 | "subs %[h], %[h], #1 \n" /* Height counter has run down? */ | ||
893 | "bgt .rowstart \n" /* More rows? */ | ||
894 | : [w]"=&r"(w), [h]"+&r"(height), [px]"=&r"(px), | ||
895 | [s]"+&r"(src), [d]"+&r"(dst) | ||
896 | : [width]"r"(width), | ||
897 | [sstp]"r"(stride - width), | ||
898 | [dstp]"r"(LCD_WIDTH - width), | ||
899 | [transcolor]"r"(TRANSPARENT_COLOR), | ||
900 | [fgcolor]"r"(REPLACEWITHFG_COLOR), | ||
901 | [fgpat]"r"(fg) | ||
902 | ); | ||
903 | } | ||
904 | #else /* optimized C version */ | ||
871 | do | 905 | do |
872 | { | 906 | { |
873 | int i; | 907 | const fb_data *src_row = src; |
874 | for(i = 0;i < width;i++) | 908 | fb_data *dst_row = dst; |
909 | fb_data *row_end = dst_row + width; | ||
910 | do | ||
875 | { | 911 | { |
876 | if (src[i] == REPLACEWITHFG_COLOR) | 912 | unsigned data = *src_row++; |
877 | dst[i] = current_vp->fg_pattern; | 913 | if (data != TRANSPARENT_COLOR) |
878 | else if(src[i] != TRANSPARENT_COLOR) | 914 | { |
879 | dst[i] = src[i]; | 915 | if (data == REPLACEWITHFG_COLOR) |
916 | *dst_row = fg; | ||
917 | else | ||
918 | *dst_row = data; | ||
919 | } | ||
880 | } | 920 | } |
921 | while (++dst_row < row_end); | ||
881 | src += stride; | 922 | src += stride; |
882 | dst += LCD_WIDTH; | 923 | dst += LCD_WIDTH; |
883 | } | 924 | } |
884 | while (dst < dst_end); | 925 | while (--height > 0); |
926 | #endif | ||
885 | } | 927 | } |
886 | #endif /* !defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR) */ | ||
887 | 928 | ||
888 | /* Draw a full native bitmap with a transparent color */ | 929 | /* Draw a full native bitmap with transparent and foreground colors */ |
889 | void lcd_bitmap_transparent(const fb_data *src, int x, int y, | 930 | void lcd_bitmap_transparent(const fb_data *src, int x, int y, |
890 | int width, int height) | 931 | int width, int height) |
891 | { | 932 | { |