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