summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/lcd-16bit-common.c96
1 files changed, 62 insertions, 34 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;