summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-16bit.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/lcd-16bit.c')
-rw-r--r--firmware/drivers/lcd-16bit.c119
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 */
838void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, 838void 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 */
889void lcd_bitmap_transparent(const fb_data *src, int x, int y, 930void lcd_bitmap_transparent(const fb_data *src, int x, int y,
890 int width, int height) 931 int width, int height)
891{ 932{