summaryrefslogtreecommitdiff
path: root/firmware/drivers/lcd-16bit-vert.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers/lcd-16bit-vert.c')
-rw-r--r--firmware/drivers/lcd-16bit-vert.c492
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
729void 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 */
908void 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 */
941static 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 */
964static inline unsigned blend_color(unsigned c, unsigned a)
965{
966 return blend_two_colors(c, current_vp->fg_pattern, a);
967}
968
969void 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 */
1203void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, 716void 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"