diff options
Diffstat (limited to 'firmware/drivers/lcd-16bit-vert.c')
-rw-r--r-- | firmware/drivers/lcd-16bit-vert.c | 492 |
1 files changed, 5 insertions, 487 deletions
diff --git a/firmware/drivers/lcd-16bit-vert.c b/firmware/drivers/lcd-16bit-vert.c index 552d80c5aa..17a1a2dda2 100644 --- a/firmware/drivers/lcd-16bit-vert.c +++ b/firmware/drivers/lcd-16bit-vert.c | |||
@@ -712,493 +712,6 @@ void lcd_fillrect(int x, int y, int width, int height) | |||
712 | while (dst < dst_end); | 712 | while (dst < dst_end); |
713 | } | 713 | } |
714 | 714 | ||
715 | /* About Rockbox' internal monochrome bitmap format: | ||
716 | * | ||
717 | * A bitmap contains one bit for every pixel that defines if that pixel is | ||
718 | * black (1) or white (0). Bits within a byte are arranged vertically, LSB | ||
719 | * at top. | ||
720 | * The bytes are stored in row-major order, with byte 0 being top left, | ||
721 | * byte 1 2nd from left etc. The first row of bytes defines pixel rows | ||
722 | * 0..7, the second row defines pixel row 8..15 etc. | ||
723 | * | ||
724 | * This is the mono bitmap format used on all other targets so far; the | ||
725 | * pixel packing doesn't really matter on a 8bit+ target. */ | ||
726 | |||
727 | /* Draw a partial monochrome bitmap */ | ||
728 | |||
729 | void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | ||
730 | int src_y, int stride, int x, int y, | ||
731 | int width, int height) | ||
732 | { | ||
733 | const unsigned char *src_end; | ||
734 | fb_data *dst, *dst_end; | ||
735 | unsigned dmask = 0x100; /* bit 8 == sentinel */ | ||
736 | int drmode = current_vp->drawmode; | ||
737 | |||
738 | /******************** Image in viewport clipping **********************/ | ||
739 | /* nothing to draw? */ | ||
740 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | ||
741 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
742 | return; | ||
743 | |||
744 | if (x < 0) | ||
745 | { | ||
746 | width += x; | ||
747 | src_x -= x; | ||
748 | x = 0; | ||
749 | } | ||
750 | if (y < 0) | ||
751 | { | ||
752 | height += y; | ||
753 | src_y -= y; | ||
754 | y = 0; | ||
755 | } | ||
756 | if (x + width > current_vp->width) | ||
757 | width = current_vp->width - x; | ||
758 | if (y + height > current_vp->height) | ||
759 | height = current_vp->height - y; | ||
760 | |||
761 | /* adjust for viewport */ | ||
762 | x += current_vp->x; | ||
763 | y += current_vp->y; | ||
764 | |||
765 | #if defined(HAVE_VIEWPORT_CLIP) | ||
766 | /********************* Viewport on screen clipping ********************/ | ||
767 | /* nothing to draw? */ | ||
768 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
769 | || (x + width <= 0) || (y + height <= 0)) | ||
770 | return; | ||
771 | |||
772 | /* clip image in viewport in screen */ | ||
773 | if (x < 0) | ||
774 | { | ||
775 | width += x; | ||
776 | src_x -= x; | ||
777 | x = 0; | ||
778 | } | ||
779 | if (y < 0) | ||
780 | { | ||
781 | height += y; | ||
782 | src_y -= y; | ||
783 | y = 0; | ||
784 | } | ||
785 | if (x + width > LCD_WIDTH) | ||
786 | width = LCD_WIDTH - x; | ||
787 | if (y + height > LCD_HEIGHT) | ||
788 | height = LCD_HEIGHT - y; | ||
789 | #endif | ||
790 | |||
791 | src += stride * (src_y >> 3) + src_x; /* move starting point */ | ||
792 | src_y &= 7; | ||
793 | src_end = src + width; | ||
794 | dst = LCDADDR(x, y); | ||
795 | dst_end = dst + height; | ||
796 | |||
797 | if (drmode & DRMODE_INVERSEVID) | ||
798 | { | ||
799 | dmask = 0x1ff; /* bit 8 == sentinel */ | ||
800 | drmode &= DRMODE_SOLID; /* mask out inversevid */ | ||
801 | } | ||
802 | |||
803 | do | ||
804 | { | ||
805 | const unsigned char *src_col = src++; | ||
806 | unsigned data = (*src_col ^ dmask) >> src_y; | ||
807 | fb_data *dst_col = dst; | ||
808 | int fg, bg; | ||
809 | long bo; | ||
810 | |||
811 | #define UPDATE_SRC do { \ | ||
812 | data >>= 1; \ | ||
813 | if (data == 0x001) { \ | ||
814 | src_col += stride; \ | ||
815 | data = *src_col ^ dmask; \ | ||
816 | } \ | ||
817 | } while (0) | ||
818 | |||
819 | switch (drmode) | ||
820 | { | ||
821 | case DRMODE_COMPLEMENT: | ||
822 | do | ||
823 | { | ||
824 | if (data & 0x01) | ||
825 | *dst_col = ~(*dst_col); | ||
826 | |||
827 | dst_col++; | ||
828 | UPDATE_SRC; | ||
829 | } | ||
830 | while (dst_col < dst_end); | ||
831 | break; | ||
832 | |||
833 | case DRMODE_BG: | ||
834 | if (lcd_backdrop) | ||
835 | { | ||
836 | bo = lcd_backdrop_offset; | ||
837 | do | ||
838 | { | ||
839 | if (!(data & 0x01)) | ||
840 | *dst_col = *(fb_data *)((long)dst_col + bo); | ||
841 | |||
842 | dst_col++; | ||
843 | UPDATE_SRC; | ||
844 | } | ||
845 | while (dst_col < dst_end); | ||
846 | } | ||
847 | else | ||
848 | { | ||
849 | bg = current_vp->bg_pattern; | ||
850 | do | ||
851 | { | ||
852 | if (!(data & 0x01)) | ||
853 | *dst_col = bg; | ||
854 | |||
855 | dst_col++; | ||
856 | UPDATE_SRC; | ||
857 | } | ||
858 | while (dst_col < dst_end); | ||
859 | } | ||
860 | break; | ||
861 | |||
862 | case DRMODE_FG: | ||
863 | fg = current_vp->fg_pattern; | ||
864 | do | ||
865 | { | ||
866 | if (data & 0x01) | ||
867 | *dst_col = fg; | ||
868 | |||
869 | dst_col++; | ||
870 | UPDATE_SRC; | ||
871 | } | ||
872 | while (dst_col < dst_end); | ||
873 | break; | ||
874 | |||
875 | case DRMODE_SOLID: | ||
876 | fg = current_vp->fg_pattern; | ||
877 | if (lcd_backdrop) | ||
878 | { | ||
879 | bo = lcd_backdrop_offset; | ||
880 | do | ||
881 | { | ||
882 | *dst_col = (data & 0x01) ? fg | ||
883 | : *(fb_data *)((long)dst_col + bo); | ||
884 | dst_col++; | ||
885 | UPDATE_SRC; | ||
886 | } | ||
887 | while (dst_col < dst_end); | ||
888 | } | ||
889 | else | ||
890 | { | ||
891 | bg = current_vp->bg_pattern; | ||
892 | do | ||
893 | { | ||
894 | *dst_col = (data & 0x01) ? fg : bg; | ||
895 | dst_col ++; | ||
896 | UPDATE_SRC; | ||
897 | } | ||
898 | while (dst_col < dst_end); | ||
899 | } | ||
900 | break; | ||
901 | } | ||
902 | |||
903 | dst += LCD_HEIGHT; | ||
904 | dst_end += LCD_HEIGHT; | ||
905 | } while (src < src_end); | ||
906 | } | ||
907 | /* Draw a full monochrome bitmap */ | ||
908 | void lcd_mono_bitmap(const unsigned char *src, int x, int y, int width, int height) | ||
909 | { | ||
910 | lcd_mono_bitmap_part(src, 0, 0, width, x, y, width, height); | ||
911 | } | ||
912 | |||
913 | /* draw alpha bitmap for anti-alias font */ | ||
914 | #define ALPHA_COLOR_FONT_DEPTH 2 | ||
915 | #define ALPHA_COLOR_LOOKUP_SHIFT (1 << ALPHA_COLOR_FONT_DEPTH) | ||
916 | #define ALPHA_COLOR_LOOKUP_SIZE ((1 << ALPHA_COLOR_LOOKUP_SHIFT) - 1) | ||
917 | #define ALPHA_COLOR_PIXEL_PER_BYTE (8 >> ALPHA_COLOR_FONT_DEPTH) | ||
918 | #define ALPHA_COLOR_PIXEL_PER_WORD (32 >> ALPHA_COLOR_FONT_DEPTH) | ||
919 | #ifdef CPU_ARM | ||
920 | #define BLEND_INIT do {} while (0) | ||
921 | #define BLEND_START(acc, color, alpha) \ | ||
922 | asm volatile("mul %0, %1, %2" : "=&r" (acc) : "r" (color), "r" (alpha)) | ||
923 | #define BLEND_CONT(acc, color, alpha) \ | ||
924 | asm volatile("mla %0, %1, %2, %0" : "+&r" (acc) : "r" (color), "r" (alpha)) | ||
925 | #define BLEND_OUT(acc) do {} while (0) | ||
926 | #elif defined(CPU_COLDFIRE) | ||
927 | #define ALPHA_BITMAP_READ_WORDS | ||
928 | #define BLEND_INIT coldfire_set_macsr(EMAC_UNSIGNED) | ||
929 | #define BLEND_START(acc, color, alpha) \ | ||
930 | asm volatile("mac.l %0, %1, %%acc0" :: "%d" (color), "d" (alpha)) | ||
931 | #define BLEND_CONT BLEND_START | ||
932 | #define BLEND_OUT(acc) asm volatile("movclr.l %%acc0, %0" : "=d" (acc)) | ||
933 | #else | ||
934 | #define BLEND_INIT do {} while (0) | ||
935 | #define BLEND_START(acc, color, alpha) ((acc) = (color) * (alpha)) | ||
936 | #define BLEND_CONT(acc, color, alpha) ((acc) += (color) * (alpha)) | ||
937 | #define BLEND_OUT(acc) do {} while (0) | ||
938 | #endif | ||
939 | |||
940 | /* Blend the given two colors */ | ||
941 | static inline unsigned blend_two_colors(unsigned c1, unsigned c2, unsigned a) | ||
942 | { | ||
943 | a += a >> (ALPHA_COLOR_LOOKUP_SHIFT - 1); | ||
944 | #if (LCD_PIXELFORMAT == RGB565SWAPPED) | ||
945 | c1 = swap16(c1); | ||
946 | c2 = swap16(c2); | ||
947 | #endif | ||
948 | unsigned c1l = (c1 | (c1 << 16)) & 0x07e0f81f; | ||
949 | unsigned c2l = (c2 | (c2 << 16)) & 0x07e0f81f; | ||
950 | unsigned p; | ||
951 | BLEND_START(p, c1l, a); | ||
952 | BLEND_CONT(p, c2l, ALPHA_COLOR_LOOKUP_SIZE + 1 - a); | ||
953 | BLEND_OUT(p); | ||
954 | p = (p >> ALPHA_COLOR_LOOKUP_SHIFT) & 0x07e0f81f; | ||
955 | p |= (p >> 16); | ||
956 | #if (LCD_PIXELFORMAT == RGB565SWAPPED) | ||
957 | return swap16(p); | ||
958 | #else | ||
959 | return p; | ||
960 | #endif | ||
961 | } | ||
962 | |||
963 | /* Blend the given color with the value from the alpha_color_lookup table */ | ||
964 | static inline unsigned blend_color(unsigned c, unsigned a) | ||
965 | { | ||
966 | return blend_two_colors(c, current_vp->fg_pattern, a); | ||
967 | } | ||
968 | |||
969 | void ICODE_ATTR lcd_alpha_bitmap_part(const unsigned char *src, int src_x, | ||
970 | int src_y, int stride, int x, int y, | ||
971 | int width, int height) | ||
972 | { | ||
973 | fb_data *dst, *dst_row, *backdrop; | ||
974 | unsigned dmask = 0x00000000; | ||
975 | int drmode = current_vp->drawmode; | ||
976 | /* nothing to draw? */ | ||
977 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | ||
978 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
979 | return; | ||
980 | /* initialize blending */ | ||
981 | BLEND_INIT; | ||
982 | |||
983 | /* clipping */ | ||
984 | if (x < 0) | ||
985 | { | ||
986 | width += x; | ||
987 | src_x -= x; | ||
988 | x = 0; | ||
989 | } | ||
990 | if (y < 0) | ||
991 | { | ||
992 | height += y; | ||
993 | src_y -= y; | ||
994 | y = 0; | ||
995 | } | ||
996 | if (x + width > current_vp->width) | ||
997 | width = current_vp->width - x; | ||
998 | if (y + height > current_vp->height) | ||
999 | height = current_vp->height - y; | ||
1000 | |||
1001 | |||
1002 | if (drmode & DRMODE_INVERSEVID) | ||
1003 | { | ||
1004 | dmask = 0xffffffff; | ||
1005 | drmode &= DRMODE_SOLID; /* mask out inversevid */ | ||
1006 | } | ||
1007 | if (drmode == DRMODE_BG) | ||
1008 | { | ||
1009 | dmask = ~dmask; | ||
1010 | } | ||
1011 | |||
1012 | /* adjust for viewport */ | ||
1013 | x += current_vp->x; | ||
1014 | y += current_vp->y; | ||
1015 | |||
1016 | #if defined(HAVE_VIEWPORT_CLIP) | ||
1017 | /********************* Viewport on screen clipping ********************/ | ||
1018 | /* nothing to draw? */ | ||
1019 | if ((x >= LCD_WIDTH) || (y >= LCD_HEIGHT) | ||
1020 | || (x + width <= 0) || (y + height <= 0)) | ||
1021 | return; | ||
1022 | |||
1023 | /* clip image in viewport in screen */ | ||
1024 | if (x < 0) | ||
1025 | { | ||
1026 | width += x; | ||
1027 | src_x -= x; | ||
1028 | x = 0; | ||
1029 | } | ||
1030 | if (y < 0) | ||
1031 | { | ||
1032 | height += y; | ||
1033 | src_y -= y; | ||
1034 | y = 0; | ||
1035 | } | ||
1036 | if (x + width > LCD_WIDTH) | ||
1037 | width = LCD_WIDTH - x; | ||
1038 | if (y + height > LCD_HEIGHT) | ||
1039 | height = LCD_HEIGHT - y; | ||
1040 | #endif | ||
1041 | |||
1042 | dst_row = dst = LCDADDR(x, y); | ||
1043 | |||
1044 | |||
1045 | int col, row = height; | ||
1046 | unsigned data, pixels; | ||
1047 | unsigned skip_end = (stride - width); | ||
1048 | unsigned skip_start = src_y * stride + src_x; | ||
1049 | |||
1050 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
1051 | uint32_t *src_w = (uint32_t *)((uintptr_t)src & ~3); | ||
1052 | skip_start += ALPHA_COLOR_PIXEL_PER_BYTE * ((uintptr_t)src & 3); | ||
1053 | src_w += skip_start / ALPHA_COLOR_PIXEL_PER_WORD; | ||
1054 | data = letoh32(*src_w++) ^ dmask; | ||
1055 | pixels = skip_start % ALPHA_COLOR_PIXEL_PER_WORD; | ||
1056 | #else | ||
1057 | src += skip_start / ALPHA_COLOR_PIXEL_PER_BYTE; | ||
1058 | data = *src ^ dmask; | ||
1059 | pixels = skip_start % ALPHA_COLOR_PIXEL_PER_BYTE; | ||
1060 | #endif | ||
1061 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
1062 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
1063 | pixels = 8 - pixels; | ||
1064 | #endif | ||
1065 | |||
1066 | do | ||
1067 | { | ||
1068 | col = width; | ||
1069 | dst = dst_row++; | ||
1070 | |||
1071 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
1072 | #define UPDATE_SRC_ALPHA do { \ | ||
1073 | if (--pixels) \ | ||
1074 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
1075 | else \ | ||
1076 | { \ | ||
1077 | data = letoh32(*src_w++) ^ dmask; \ | ||
1078 | pixels = ALPHA_COLOR_PIXEL_PER_WORD; \ | ||
1079 | } \ | ||
1080 | } while (0) | ||
1081 | #elif ALPHA_COLOR_PIXEL_PER_BYTE == 2 | ||
1082 | #define UPDATE_SRC_ALPHA do { \ | ||
1083 | if (pixels ^= 1) \ | ||
1084 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
1085 | else \ | ||
1086 | data = *(++src) ^ dmask; \ | ||
1087 | } while (0) | ||
1088 | #else | ||
1089 | #define UPDATE_SRC_ALPHA do { \ | ||
1090 | if (pixels = (++pixels % ALPHA_COLOR_PIXEL_PER_BYTE)) \ | ||
1091 | data >>= ALPHA_COLOR_LOOKUP_SHIFT; \ | ||
1092 | else \ | ||
1093 | data = *(++src) ^ dmask; \ | ||
1094 | } while (0) | ||
1095 | #endif | ||
1096 | /* we don't want to have this in our inner | ||
1097 | * loop and the codesize increase is minimal */ | ||
1098 | switch (drmode) | ||
1099 | { | ||
1100 | case DRMODE_COMPLEMENT: | ||
1101 | do | ||
1102 | { | ||
1103 | *dst=blend_two_colors(*dst, ~(*dst), | ||
1104 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1105 | dst += LCD_HEIGHT; | ||
1106 | UPDATE_SRC_ALPHA; | ||
1107 | } | ||
1108 | while (--col); | ||
1109 | break; | ||
1110 | case DRMODE_BG: | ||
1111 | if(lcd_backdrop) | ||
1112 | { | ||
1113 | backdrop = (fb_data *)((long)dst+lcd_backdrop_offset); | ||
1114 | do | ||
1115 | { | ||
1116 | *dst=blend_two_colors(*dst, *backdrop, | ||
1117 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1118 | dst += LCD_HEIGHT; | ||
1119 | backdrop += LCD_HEIGHT; | ||
1120 | UPDATE_SRC_ALPHA; | ||
1121 | } | ||
1122 | while (--col); | ||
1123 | } | ||
1124 | else | ||
1125 | { | ||
1126 | do | ||
1127 | { | ||
1128 | *dst=blend_two_colors(*dst, current_vp->bg_pattern, | ||
1129 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1130 | dst += LCD_HEIGHT; | ||
1131 | UPDATE_SRC_ALPHA; | ||
1132 | } | ||
1133 | while (--col); | ||
1134 | } | ||
1135 | break; | ||
1136 | case DRMODE_FG: | ||
1137 | do | ||
1138 | { | ||
1139 | *dst=blend_color(*dst, data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1140 | dst += LCD_HEIGHT; | ||
1141 | UPDATE_SRC_ALPHA; | ||
1142 | } | ||
1143 | while (--col); | ||
1144 | break; | ||
1145 | case DRMODE_SOLID: | ||
1146 | if(lcd_backdrop) | ||
1147 | { | ||
1148 | backdrop = (fb_data *)((long)dst+lcd_backdrop_offset); | ||
1149 | do | ||
1150 | { | ||
1151 | *(dst)=blend_color(*backdrop, | ||
1152 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1153 | dst += LCD_HEIGHT; | ||
1154 | backdrop += LCD_HEIGHT; | ||
1155 | UPDATE_SRC_ALPHA; | ||
1156 | } | ||
1157 | while (--col); | ||
1158 | } | ||
1159 | else | ||
1160 | { | ||
1161 | do | ||
1162 | { | ||
1163 | *(dst)=blend_color(current_vp->bg_pattern, | ||
1164 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1165 | dst += LCD_HEIGHT; | ||
1166 | UPDATE_SRC_ALPHA; | ||
1167 | } | ||
1168 | while (--col); | ||
1169 | } | ||
1170 | break; | ||
1171 | } | ||
1172 | #ifdef ALPHA_BITMAP_READ_WORDS | ||
1173 | if (skip_end < pixels) | ||
1174 | { | ||
1175 | pixels -= skip_end; | ||
1176 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | ||
1177 | } else { | ||
1178 | pixels = skip_end - pixels; | ||
1179 | src_w += pixels / ALPHA_COLOR_PIXEL_PER_WORD; | ||
1180 | pixels %= ALPHA_COLOR_PIXEL_PER_WORD; | ||
1181 | data = letoh32(*src_w++) ^ dmask; | ||
1182 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
1183 | pixels = 8 - pixels; | ||
1184 | } | ||
1185 | #else | ||
1186 | if (skip_end) | ||
1187 | { | ||
1188 | pixels += skip_end; | ||
1189 | if (pixels >= ALPHA_COLOR_PIXEL_PER_BYTE) | ||
1190 | { | ||
1191 | src += pixels / ALPHA_COLOR_PIXEL_PER_BYTE; | ||
1192 | pixels %= ALPHA_COLOR_PIXEL_PER_BYTE; | ||
1193 | data = *src ^ dmask; | ||
1194 | data >>= pixels * ALPHA_COLOR_LOOKUP_SHIFT; | ||
1195 | } else | ||
1196 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | ||
1197 | } | ||
1198 | #endif | ||
1199 | } while (--row); | ||
1200 | } | ||
1201 | |||
1202 | /* Draw a partial native bitmap */ | 715 | /* Draw a partial native bitmap */ |
1203 | void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | 716 | void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, |
1204 | int stride, int x, int y, int width, | 717 | int stride, int x, int y, int width, |
@@ -1371,4 +884,9 @@ void lcd_bitmap_transparent(const fb_data *src, int x, int y, | |||
1371 | STRIDE(SCREEN_MAIN, width, height), x, y, width, height); | 884 | STRIDE(SCREEN_MAIN, width, height), x, y, width, height); |
1372 | } | 885 | } |
1373 | 886 | ||
887 | #define ROW_INC 1 | ||
888 | #define COL_INC LCD_HEIGHT | ||
889 | |||
890 | #include "lcd-16bit-common.c" | ||
891 | |||
1374 | #include "lcd-bitmap-common.c" | 892 | #include "lcd-bitmap-common.c" |