diff options
-rw-r--r-- | firmware/drivers/lcd-16bit-common.c | 96 | ||||
-rw-r--r-- | firmware/export/lcd.h | 3 |
2 files changed, 64 insertions, 35 deletions
diff --git a/firmware/drivers/lcd-16bit-common.c b/firmware/drivers/lcd-16bit-common.c index dffc1cf075..99cbe489fc 100644 --- a/firmware/drivers/lcd-16bit-common.c +++ b/firmware/drivers/lcd-16bit-common.c | |||
@@ -623,7 +623,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
623 | 623 | ||
624 | /* Use extra bit to avoid if () in the switch-cases below */ | 624 | /* Use extra bit to avoid if () in the switch-cases below */ |
625 | if ((drmode & DRMODE_BG) && lcd_backdrop) | 625 | if ((drmode & DRMODE_BG) && lcd_backdrop) |
626 | drmode |= DRMODE_INT_MOD; | 626 | drmode |= DRMODE_INT_BD; |
627 | 627 | ||
628 | /* go through each column and update each pixel */ | 628 | /* go through each column and update each pixel */ |
629 | do | 629 | do |
@@ -659,7 +659,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
659 | while (--row); | 659 | while (--row); |
660 | break; | 660 | break; |
661 | 661 | ||
662 | case DRMODE_BG|DRMODE_INT_MOD: | 662 | case DRMODE_BG|DRMODE_INT_BD: |
663 | bo = lcd_backdrop_offset; | 663 | bo = lcd_backdrop_offset; |
664 | do | 664 | do |
665 | { | 665 | { |
@@ -698,7 +698,7 @@ void ICODE_ATTR lcd_mono_bitmap_part(const unsigned char *src, int src_x, | |||
698 | while (--row); | 698 | while (--row); |
699 | break; | 699 | break; |
700 | 700 | ||
701 | case DRMODE_SOLID|DRMODE_INT_MOD: | 701 | case DRMODE_SOLID|DRMODE_INT_BD: |
702 | fg = current_vp->fg_pattern; | 702 | fg = current_vp->fg_pattern; |
703 | bo = lcd_backdrop_offset; | 703 | bo = lcd_backdrop_offset; |
704 | do | 704 | do |
@@ -817,7 +817,6 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
817 | int stride_image, int stride_src) | 817 | int stride_image, int stride_src) |
818 | { | 818 | { |
819 | fb_data *dst, *dst_row; | 819 | fb_data *dst, *dst_row; |
820 | const fb_data *image_row; | ||
821 | unsigned dmask = 0x00000000; | 820 | unsigned dmask = 0x00000000; |
822 | int drmode = current_vp->drawmode; | 821 | int drmode = current_vp->drawmode; |
823 | /* nothing to draw? */ | 822 | /* nothing to draw? */ |
@@ -878,21 +877,33 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
878 | height = LCD_HEIGHT - y; | 877 | height = LCD_HEIGHT - y; |
879 | #endif | 878 | #endif |
880 | 879 | ||
880 | /* the following drawmode combinations are possible: | ||
881 | * 1) COMPLEMENT: just negates the framebuffer contents | ||
882 | * 2) BG and BG+backdrop: draws _only_ background pixels with either | ||
883 | * the background color or the backdrop (if any). The backdrop | ||
884 | * is an image in native lcd format | ||
885 | * 3) FG and FG+image: draws _only_ foreground pixels with either | ||
886 | * the foreground color or an image buffer. The image is in | ||
887 | * native lcd format | ||
888 | * 4) SOLID, SOLID+backdrop, SOLID+image, SOLID+backdrop+image, i.e. all | ||
889 | * possible combinations of 2) and 3). Draws both, fore- and background, | ||
890 | * pixels. The rules of 2) and 3) apply. | ||
891 | * | ||
892 | * INVERSEVID swaps fore- and background pixels, i.e. background pixels | ||
893 | * become foreground ones and vice versa. | ||
894 | */ | ||
881 | if (drmode & DRMODE_INVERSEVID) | 895 | if (drmode & DRMODE_INVERSEVID) |
882 | { | 896 | { |
883 | dmask = 0xffffffff; | 897 | dmask = 0xffffffff; |
884 | drmode &= DRMODE_SOLID; /* mask out inversevid */ | 898 | drmode &= DRMODE_SOLID; /* mask out inversevid */ |
885 | } | 899 | } |
886 | if (drmode == DRMODE_BG) | 900 | |
887 | dmask = ~dmask; | 901 | /* Use extra bits to avoid if () in the switch-cases below */ |
888 | /* If drawmode is FG use a separate special case that blends the image | ||
889 | * onto the current framebuffer contents. Otherwise BG is forced that | ||
890 | * blends the image with the backdrop (if any, otherwise background color )*/ | ||
891 | if (image != NULL) | 902 | if (image != NULL) |
892 | drmode = (drmode == DRMODE_FG) ? DRMODE_FG|DRMODE_INT_MOD : DRMODE_BG; | 903 | drmode |= DRMODE_INT_IMG; |
893 | /* Use extra bit to avoid if () in the switch-cases below */ | 904 | |
894 | if ((drmode & DRMODE_BG) && lcd_backdrop) | 905 | if ((drmode & DRMODE_BG) && lcd_backdrop) |
895 | drmode |= DRMODE_INT_MOD; | 906 | drmode |= DRMODE_INT_BD; |
896 | 907 | ||
897 | dst_row = FBADDR(x, y); | 908 | dst_row = FBADDR(x, y); |
898 | 909 | ||
@@ -918,10 +929,11 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
918 | #ifdef ALPHA_BITMAP_READ_WORDS | 929 | #ifdef ALPHA_BITMAP_READ_WORDS |
919 | pixels = 8 - pixels; | 930 | pixels = 8 - pixels; |
920 | #endif | 931 | #endif |
921 | if (image) | ||
922 | image += skip_start_image; | ||
923 | image_row = image; | ||
924 | 932 | ||
933 | /* image is only accessed in DRMODE_INT_IMG cases, i.e. when non-NULL. | ||
934 | * Therefore NULL accesses are impossible and we can increment | ||
935 | * unconditionally (applies for stride at the end of the loop as well) */ | ||
936 | image += skip_start_image; | ||
925 | /* go through the rows and update each pixel */ | 937 | /* go through the rows and update each pixel */ |
926 | do | 938 | do |
927 | { | 939 | { |
@@ -929,16 +941,10 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
929 | * temp vars just before the loop helps gcc to opimize the loop better | 941 | * temp vars just before the loop helps gcc to opimize the loop better |
930 | * (testing showed ~15% speedup) */ | 942 | * (testing showed ~15% speedup) */ |
931 | unsigned fg, bg; | 943 | unsigned fg, bg; |
932 | uintptr_t bo; | 944 | ptrdiff_t bo, img_offset; |
933 | col = width; | 945 | col = width; |
934 | dst = dst_row; | 946 | dst = dst_row; |
935 | dst_row += ROW_INC; | 947 | dst_row += ROW_INC; |
936 | if (image_row) { | ||
937 | image = image_row; | ||
938 | image_row += STRIDE_MAIN(stride_image,1); | ||
939 | } | ||
940 | else | ||
941 | image = dst; | ||
942 | #ifdef ALPHA_BITMAP_READ_WORDS | 948 | #ifdef ALPHA_BITMAP_READ_WORDS |
943 | #define UPDATE_SRC_ALPHA do { \ | 949 | #define UPDATE_SRC_ALPHA do { \ |
944 | if (--pixels) \ | 950 | if (--pixels) \ |
@@ -964,8 +970,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
964 | data = *(++src) ^ dmask; \ | 970 | data = *(++src) ^ dmask; \ |
965 | } while (0) | 971 | } while (0) |
966 | #endif | 972 | #endif |
967 | /* we don't want to have this in our inner | 973 | |
968 | * loop and the codesize increase is minimal */ | ||
969 | switch (drmode) | 974 | switch (drmode) |
970 | { | 975 | { |
971 | case DRMODE_COMPLEMENT: | 976 | case DRMODE_COMPLEMENT: |
@@ -978,12 +983,12 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
978 | } | 983 | } |
979 | while (--col); | 984 | while (--col); |
980 | break; | 985 | break; |
981 | case DRMODE_BG|DRMODE_INT_MOD: | 986 | case DRMODE_BG|DRMODE_INT_BD: |
982 | bo = lcd_backdrop_offset; | 987 | bo = lcd_backdrop_offset; |
983 | do | 988 | do |
984 | { | 989 | { |
985 | fb_data c = *(fb_data *)((uintptr_t)dst + bo); | 990 | fb_data c = *(fb_data *)((uintptr_t)dst + bo); |
986 | *dst = blend_two_colors(c, *image, data & ALPHA_COLOR_LOOKUP_SIZE ); | 991 | *dst = blend_two_colors(c, *dst, data & ALPHA_COLOR_LOOKUP_SIZE ); |
987 | dst += COL_INC; | 992 | dst += COL_INC; |
988 | image += STRIDE_MAIN(1, stride_image); | 993 | image += STRIDE_MAIN(1, stride_image); |
989 | UPDATE_SRC_ALPHA; | 994 | UPDATE_SRC_ALPHA; |
@@ -994,19 +999,18 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
994 | bg = current_vp->bg_pattern; | 999 | bg = current_vp->bg_pattern; |
995 | do | 1000 | do |
996 | { | 1001 | { |
997 | *dst = blend_two_colors(bg, *image, data & ALPHA_COLOR_LOOKUP_SIZE ); | 1002 | *dst = blend_two_colors(bg, *dst, data & ALPHA_COLOR_LOOKUP_SIZE ); |
998 | dst += COL_INC; | 1003 | dst += COL_INC; |
999 | image += STRIDE_MAIN(1, stride_image); | ||
1000 | UPDATE_SRC_ALPHA; | 1004 | UPDATE_SRC_ALPHA; |
1001 | } | 1005 | } |
1002 | while (--col); | 1006 | while (--col); |
1003 | break; | 1007 | break; |
1004 | case DRMODE_FG|DRMODE_INT_MOD: | 1008 | case DRMODE_FG|DRMODE_INT_IMG: |
1009 | img_offset = image - dst; | ||
1005 | do | 1010 | do |
1006 | { | 1011 | { |
1007 | *dst = blend_two_colors(*dst, *image, data & ALPHA_COLOR_LOOKUP_SIZE ); | 1012 | *dst = blend_two_colors(*dst, *(dst + img_offset), data & ALPHA_COLOR_LOOKUP_SIZE ); |
1008 | dst += COL_INC; | 1013 | dst += COL_INC; |
1009 | image += STRIDE_MAIN(1, stride_image); | ||
1010 | UPDATE_SRC_ALPHA; | 1014 | UPDATE_SRC_ALPHA; |
1011 | } | 1015 | } |
1012 | while (--col); | 1016 | while (--col); |
@@ -1021,7 +1025,7 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
1021 | } | 1025 | } |
1022 | while (--col); | 1026 | while (--col); |
1023 | break; | 1027 | break; |
1024 | case DRMODE_SOLID|DRMODE_INT_MOD: | 1028 | case DRMODE_SOLID|DRMODE_INT_BD: |
1025 | bo = lcd_backdrop_offset; | 1029 | bo = lcd_backdrop_offset; |
1026 | fg = current_vp->fg_pattern; | 1030 | fg = current_vp->fg_pattern; |
1027 | do | 1031 | do |
@@ -1033,13 +1037,35 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
1033 | } | 1037 | } |
1034 | while (--col); | 1038 | while (--col); |
1035 | break; | 1039 | break; |
1040 | case DRMODE_SOLID|DRMODE_INT_IMG: | ||
1041 | bg = current_vp->bg_pattern; | ||
1042 | img_offset = image - dst; | ||
1043 | do | ||
1044 | { | ||
1045 | *dst = blend_two_colors(bg, *(dst + img_offset), data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1046 | dst += COL_INC; | ||
1047 | UPDATE_SRC_ALPHA; | ||
1048 | } | ||
1049 | while (--col); | ||
1050 | break; | ||
1051 | case DRMODE_SOLID|DRMODE_INT_BD|DRMODE_INT_IMG: | ||
1052 | bo = lcd_backdrop_offset; | ||
1053 | img_offset = image - dst; | ||
1054 | do | ||
1055 | { | ||
1056 | fb_data *c = (fb_data *)((uintptr_t)dst + bo); | ||
1057 | *dst = blend_two_colors(*c, *(dst + img_offset), data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1058 | dst += COL_INC; | ||
1059 | UPDATE_SRC_ALPHA; | ||
1060 | } | ||
1061 | while (--col); | ||
1062 | break; | ||
1036 | case DRMODE_SOLID: | 1063 | case DRMODE_SOLID: |
1037 | bg = current_vp->bg_pattern; | 1064 | bg = current_vp->bg_pattern; |
1038 | fg = current_vp->fg_pattern; | 1065 | fg = current_vp->fg_pattern; |
1039 | do | 1066 | do |
1040 | { | 1067 | { |
1041 | *dst = blend_two_colors(bg, fg, | 1068 | *dst = blend_two_colors(bg, fg, data & ALPHA_COLOR_LOOKUP_SIZE ); |
1042 | data & ALPHA_COLOR_LOOKUP_SIZE ); | ||
1043 | dst += COL_INC; | 1069 | dst += COL_INC; |
1044 | UPDATE_SRC_ALPHA; | 1070 | UPDATE_SRC_ALPHA; |
1045 | } | 1071 | } |
@@ -1073,6 +1099,8 @@ static void ICODE_ATTR lcd_alpha_bitmap_part_mix(const fb_data* image, | |||
1073 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; | 1099 | data >>= skip_end * ALPHA_COLOR_LOOKUP_SHIFT; |
1074 | } | 1100 | } |
1075 | #endif | 1101 | #endif |
1102 | |||
1103 | image += STRIDE_MAIN(stride_image,1); | ||
1076 | } while (--row); | 1104 | } while (--row); |
1077 | 1105 | ||
1078 | BLEND_FINISH; | 1106 | BLEND_FINISH; |
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index f6b32a37ee..7842ce59f2 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h | |||
@@ -287,7 +287,8 @@ extern void lcd_jump_scroll_delay(int ms); | |||
287 | #define DRMODE_SOLID 3 | 287 | #define DRMODE_SOLID 3 |
288 | #define DRMODE_INVERSEVID 4 /* used as bit modifier for basic modes */ | 288 | #define DRMODE_INVERSEVID 4 /* used as bit modifier for basic modes */ |
289 | /* Internal drawmode modifiers. DO NOT use with set_drawmode() */ | 289 | /* Internal drawmode modifiers. DO NOT use with set_drawmode() */ |
290 | #define DRMODE_INT_MOD 8 | 290 | #define DRMODE_INT_BD 8 |
291 | #define DRMODE_INT_IMG 16 | ||
291 | 292 | ||
292 | /* Low-level drawing function types */ | 293 | /* Low-level drawing function types */ |
293 | typedef void lcd_pixelfunc_type(int x, int y); | 294 | typedef void lcd_pixelfunc_type(int x, int y); |