diff options
author | Jens Arnold <amiconn@rockbox.org> | 2009-10-26 01:35:31 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2009-10-26 01:35:31 +0000 |
commit | 5365cbe0a5af0ef357e7fc70e793141ccd38f23e (patch) | |
tree | 9682db5ae001f4fee09f9ba9bea4e650fdc96d97 | |
parent | dd0afc5aa28ab5117056dda3cb19a283ece56ef4 (diff) | |
download | rockbox-5365cbe0a5af0ef357e7fc70e793141ccd38f23e.tar.gz rockbox-5365cbe0a5af0ef357e7fc70e793141ccd38f23e.zip |
Color targets: Ported assembler optimised transparent bitmap drawing from Gigabeat S/F/X to all ARM targets (~23..40% speedup). * C optimised transparent bitmap drawing for non-ARM targets and sims. * Use the more compact boundary checking for non-transparent native bitmap drawing as well.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23353 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/drivers/lcd-16bit.c | 119 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c | 63 | ||||
-rw-r--r-- | firmware/target/arm/s3c2440/lcd-s3c2440.c | 65 |
3 files changed, 80 insertions, 167 deletions
diff --git a/firmware/drivers/lcd-16bit.c b/firmware/drivers/lcd-16bit.c index d1b417a00a..cee6c2aeef 100644 --- a/firmware/drivers/lcd-16bit.c +++ b/firmware/drivers/lcd-16bit.c | |||
@@ -788,34 +788,36 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
788 | int stride, int x, int y, int width, | 788 | int stride, int x, int y, int width, |
789 | int height) | 789 | int height) |
790 | { | 790 | { |
791 | fb_data *dst, *dst_end; | 791 | fb_data *dst; |
792 | 792 | ||
793 | /* nothing to draw? */ | 793 | if (x + width > current_vp->width) |
794 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 794 | width = current_vp->width - x; /* Clip right */ |
795 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
796 | return; | ||
797 | 795 | ||
798 | /* clipping */ | 796 | if (x < 0) /* Clip left */ |
799 | if (x < 0) | ||
800 | { | 797 | { |
801 | width += x; | 798 | width += x; |
802 | src_x -= x; | 799 | src_x -= x; |
803 | x = 0; | 800 | x = 0; |
804 | } | 801 | } |
805 | if (y < 0) | 802 | |
803 | if (width <= 0) | ||
804 | return; /* nothing left to do */ | ||
805 | |||
806 | if (y + height > current_vp->height) | ||
807 | height = current_vp->height - y; /* Clip bottom */ | ||
808 | |||
809 | if (y < 0) /* Clip top */ | ||
806 | { | 810 | { |
807 | height += y; | 811 | height += y; |
808 | src_y -= y; | 812 | src_y -= y; |
809 | y = 0; | 813 | y = 0; |
810 | } | 814 | } |
811 | if (x + width > current_vp->width) | 815 | |
812 | width = current_vp->width - x; | 816 | if (height <= 0) |
813 | if (y + height > current_vp->height) | 817 | return; /* nothing left to do */ |
814 | height = current_vp->height - y; | ||
815 | 818 | ||
816 | src += stride * src_y + src_x; /* move starting point */ | 819 | src += stride * src_y + src_x; /* move starting point */ |
817 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 820 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); |
818 | dst_end = dst + height * LCD_WIDTH; | ||
819 | 821 | ||
820 | do | 822 | do |
821 | { | 823 | { |
@@ -823,7 +825,7 @@ void ICODE_ATTR lcd_bitmap_part(const fb_data *src, int src_x, int src_y, | |||
823 | src += stride; | 825 | src += stride; |
824 | dst += LCD_WIDTH; | 826 | dst += LCD_WIDTH; |
825 | } | 827 | } |
826 | while (dst < dst_end); | 828 | while (--height > 0); |
827 | } | 829 | } |
828 | 830 | ||
829 | /* Draw a full native bitmap */ | 831 | /* Draw a full native bitmap */ |
@@ -832,60 +834,99 @@ void lcd_bitmap(const fb_data *src, int x, int y, int width, int height) | |||
832 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); | 834 | lcd_bitmap_part(src, 0, 0, width, x, y, width, height); |
833 | } | 835 | } |
834 | 836 | ||
835 | #if !defined(TOSHIBA_GIGABEAT_F) && !defined(TOSHIBA_GIGABEAT_S) \ | 837 | /* Draw a partial native bitmap with transparency and foreground colors */ |
836 | || defined(SIMULATOR) | ||
837 | /* Draw a partial native bitmap */ | ||
838 | void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, | 838 | void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, |
839 | int src_y, int stride, int x, | 839 | int src_y, int stride, int x, |
840 | int y, int width, int height) | 840 | int y, int width, int height) |
841 | { | 841 | { |
842 | fb_data *dst, *dst_end; | 842 | fb_data *dst; |
843 | unsigned fg = current_vp->fg_pattern; | ||
843 | 844 | ||
844 | /* nothing to draw? */ | 845 | if (x + width > current_vp->width) |
845 | if ((width <= 0) || (height <= 0) || (x >= current_vp->width) || | 846 | width = current_vp->width - x; /* Clip right */ |
846 | (y >= current_vp->height) || (x + width <= 0) || (y + height <= 0)) | ||
847 | return; | ||
848 | 847 | ||
849 | /* clipping */ | 848 | if (x < 0) /* Clip left */ |
850 | if (x < 0) | ||
851 | { | 849 | { |
852 | width += x; | 850 | width += x; |
853 | src_x -= x; | 851 | src_x -= x; |
854 | x = 0; | 852 | x = 0; |
855 | } | 853 | } |
856 | if (y < 0) | 854 | |
855 | if (width <= 0) | ||
856 | return; /* nothing left to do */ | ||
857 | |||
858 | if (y + height > current_vp->height) | ||
859 | height = current_vp->height - y; /* Clip bottom */ | ||
860 | |||
861 | if (y < 0) /* Clip top */ | ||
857 | { | 862 | { |
858 | height += y; | 863 | height += y; |
859 | src_y -= y; | 864 | src_y -= y; |
860 | y = 0; | 865 | y = 0; |
861 | } | 866 | } |
862 | if (x + width > current_vp->width) | 867 | |
863 | width = current_vp->width - x; | 868 | if (height <= 0) |
864 | if (y + height > current_vp->height) | 869 | return; /* nothing left to do */ |
865 | height = current_vp->height - y; | ||
866 | 870 | ||
867 | src += stride * src_y + src_x; /* move starting point */ | 871 | src += stride * src_y + src_x; /* move starting point */ |
868 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); | 872 | dst = LCDADDR(current_vp->x + x, current_vp->y + y); |
869 | dst_end = dst + height * LCD_WIDTH; | ||
870 | 873 | ||
874 | #ifdef CPU_ARM | ||
875 | { | ||
876 | int w, px; | ||
877 | asm volatile ( | ||
878 | ".rowstart: \n" | ||
879 | "mov %[w], %[width] \n" /* Load width for inner loop */ | ||
880 | ".nextpixel: \n" | ||
881 | "ldrh %[px], [%[s]], #2 \n" /* Load src pixel */ | ||
882 | "add %[d], %[d], #2 \n" /* Uncoditionally increment dst */ | ||
883 | /* done here for better pipelining */ | ||
884 | "cmp %[px], %[fgcolor] \n" /* Compare to foreground color */ | ||
885 | "streqh %[fgpat], [%[d], #-2] \n" /* Store foregroud if match */ | ||
886 | "cmpne %[px], %[transcolor] \n" /* Compare to transparent color */ | ||
887 | "strneh %[px], [%[d], #-2] \n" /* Store dst if not transparent */ | ||
888 | "subs %[w], %[w], #1 \n" /* Width counter has run down? */ | ||
889 | "bgt .nextpixel \n" /* More in this row? */ | ||
890 | "add %[s], %[s], %[sstp], lsl #1 \n" /* Skip over to start of next line */ | ||
891 | "add %[d], %[d], %[dstp], lsl #1 \n" | ||
892 | "subs %[h], %[h], #1 \n" /* Height counter has run down? */ | ||
893 | "bgt .rowstart \n" /* More rows? */ | ||
894 | : [w]"=&r"(w), [h]"+&r"(height), [px]"=&r"(px), | ||
895 | [s]"+&r"(src), [d]"+&r"(dst) | ||
896 | : [width]"r"(width), | ||
897 | [sstp]"r"(stride - width), | ||
898 | [dstp]"r"(LCD_WIDTH - width), | ||
899 | [transcolor]"r"(TRANSPARENT_COLOR), | ||
900 | [fgcolor]"r"(REPLACEWITHFG_COLOR), | ||
901 | [fgpat]"r"(fg) | ||
902 | ); | ||
903 | } | ||
904 | #else /* optimized C version */ | ||
871 | do | 905 | do |
872 | { | 906 | { |
873 | int i; | 907 | const fb_data *src_row = src; |
874 | for(i = 0;i < width;i++) | 908 | fb_data *dst_row = dst; |
909 | fb_data *row_end = dst_row + width; | ||
910 | do | ||
875 | { | 911 | { |
876 | if (src[i] == REPLACEWITHFG_COLOR) | 912 | unsigned data = *src_row++; |
877 | dst[i] = current_vp->fg_pattern; | 913 | if (data != TRANSPARENT_COLOR) |
878 | else if(src[i] != TRANSPARENT_COLOR) | 914 | { |
879 | dst[i] = src[i]; | 915 | if (data == REPLACEWITHFG_COLOR) |
916 | *dst_row = fg; | ||
917 | else | ||
918 | *dst_row = data; | ||
919 | } | ||
880 | } | 920 | } |
921 | while (++dst_row < row_end); | ||
881 | src += stride; | 922 | src += stride; |
882 | dst += LCD_WIDTH; | 923 | dst += LCD_WIDTH; |
883 | } | 924 | } |
884 | while (dst < dst_end); | 925 | while (--height > 0); |
926 | #endif | ||
885 | } | 927 | } |
886 | #endif /* !defined(TOSHIBA_GIGABEAT_F) || defined(SIMULATOR) */ | ||
887 | 928 | ||
888 | /* Draw a full native bitmap with a transparent color */ | 929 | /* Draw a full native bitmap with transparent and foreground colors */ |
889 | void lcd_bitmap_transparent(const fb_data *src, int x, int y, | 930 | void lcd_bitmap_transparent(const fb_data *src, int x, int y, |
890 | int width, int height) | 931 | int width, int height) |
891 | { | 932 | { |
diff --git a/firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c b/firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c index fa1aed0fd6..ea3bfaf519 100644 --- a/firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c | |||
@@ -146,69 +146,6 @@ void lcd_update(void) | |||
146 | LCD_WIDTH*LCD_HEIGHT, 1); | 146 | LCD_WIDTH*LCD_HEIGHT, 1); |
147 | } | 147 | } |
148 | 148 | ||
149 | void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | ||
150 | int stride, int x, int y, int width, | ||
151 | int height) | ||
152 | { | ||
153 | int w, px; | ||
154 | fb_data *dst; | ||
155 | |||
156 | if (x + width > current_vp->width) | ||
157 | width = current_vp->width - x; /* Clip right */ | ||
158 | |||
159 | if (x < 0) /* Clip left */ | ||
160 | { | ||
161 | width += x; | ||
162 | src_x -= x; | ||
163 | x = 0; | ||
164 | } | ||
165 | |||
166 | if (width <= 0) | ||
167 | return; /* nothing left to do */ | ||
168 | |||
169 | if (y + height > current_vp->height) | ||
170 | height = current_vp->height - y; /* Clip bottom */ | ||
171 | |||
172 | if (y < 0) /* Clip top */ | ||
173 | { | ||
174 | height += y; | ||
175 | src_y -= y; | ||
176 | y = 0; | ||
177 | } | ||
178 | |||
179 | if (height <= 0) | ||
180 | return; /* nothing left to do */ | ||
181 | |||
182 | src += stride * src_y + src_x; /* move starting point */ | ||
183 | dst = &lcd_framebuffer[current_vp->y+y][current_vp->x+x]; | ||
184 | |||
185 | asm volatile ( | ||
186 | ".rowstart: \r\n" | ||
187 | "mov %[w], %[width] \r\n" /* Load width for inner loop */ | ||
188 | ".nextpixel: \r\n" | ||
189 | "ldrh %[px], [%[s]], #2 \r\n" /* Load src pixel */ | ||
190 | "add %[d], %[d], #2 \r\n" /* Uncoditionally increment dst */ | ||
191 | "cmp %[px], %[fgcolor] \r\n" /* Compare to foreground color */ | ||
192 | "streqh %[fgpat], [%[d], #-2] \r\n" /* Store foregroud if match */ | ||
193 | "cmpne %[px], %[transcolor] \r\n" /* Compare to transparent color */ | ||
194 | "strneh %[px], [%[d], #-2] \r\n" /* Store dst if not transparent */ | ||
195 | "subs %[w], %[w], #1 \r\n" /* Width counter has run down? */ | ||
196 | "bgt .nextpixel \r\n" /* More in this row? */ | ||
197 | "add %[s], %[s], %[sstp], lsl #1 \r\n" /* Skip over to start of next line */ | ||
198 | "add %[d], %[d], %[dstp], lsl #1 \r\n" | ||
199 | "subs %[h], %[h], #1 \r\n" /* Height counter has run down? */ | ||
200 | "bgt .rowstart \r\n" /* More rows? */ | ||
201 | : [w]"=&r"(w), [h]"+&r"(height), [px]"=&r"(px), | ||
202 | [s]"+&r"(src), [d]"+&r"(dst) | ||
203 | : [width]"r"(width), | ||
204 | [sstp]"r"(stride - width), | ||
205 | [dstp]"r"(LCD_WIDTH - width), | ||
206 | [transcolor]"r"(TRANSPARENT_COLOR), | ||
207 | [fgcolor]"r"(REPLACEWITHFG_COLOR), | ||
208 | [fgpat]"r"(current_vp->fg_pattern) | ||
209 | ); | ||
210 | } | ||
211 | |||
212 | void lcd_yuv_set_options(unsigned options) | 149 | void lcd_yuv_set_options(unsigned options) |
213 | { | 150 | { |
214 | lcd_yuv_options = options; | 151 | lcd_yuv_options = options; |
diff --git a/firmware/target/arm/s3c2440/lcd-s3c2440.c b/firmware/target/arm/s3c2440/lcd-s3c2440.c index d702b5713a..4a4674e87f 100644 --- a/firmware/target/arm/s3c2440/lcd-s3c2440.c +++ b/firmware/target/arm/s3c2440/lcd-s3c2440.c | |||
@@ -455,71 +455,6 @@ void lcd_update(void) | |||
455 | LCD_WIDTH*LCD_HEIGHT, 1); | 455 | LCD_WIDTH*LCD_HEIGHT, 1); |
456 | } | 456 | } |
457 | 457 | ||
458 | #if defined(TOSHIBA_GIGABEAT_F) || defined(TOSHIBA_GIGABEAT_S) | ||
459 | void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | ||
460 | int stride, int x, int y, int width, | ||
461 | int height) | ||
462 | { | ||
463 | int w, px; | ||
464 | fb_data *dst; | ||
465 | |||
466 | if (x + width > current_vp->width) | ||
467 | width = current_vp->width - x; /* Clip right */ | ||
468 | |||
469 | if (x < 0) /* Clip left */ | ||
470 | { | ||
471 | width += x; | ||
472 | src_x -= x; | ||
473 | x = 0; | ||
474 | } | ||
475 | |||
476 | if (width <= 0) | ||
477 | return; /* nothing left to do */ | ||
478 | |||
479 | if (y + height > current_vp->height) | ||
480 | height = current_vp->height - y; /* Clip bottom */ | ||
481 | |||
482 | if (y < 0) /* Clip top */ | ||
483 | { | ||
484 | height += y; | ||
485 | src_y -= y; | ||
486 | y = 0; | ||
487 | } | ||
488 | |||
489 | if (height <= 0) | ||
490 | return; /* nothing left to do */ | ||
491 | |||
492 | src += stride * src_y + src_x; /* move starting point */ | ||
493 | dst = &lcd_framebuffer[current_vp->y+y][current_vp->x+x]; | ||
494 | |||
495 | asm volatile ( | ||
496 | ".rowstart: \r\n" | ||
497 | "mov %[w], %[width] \r\n" /* Load width for inner loop */ | ||
498 | ".nextpixel: \r\n" | ||
499 | "ldrh %[px], [%[s]], #2 \r\n" /* Load src pixel */ | ||
500 | "add %[d], %[d], #2 \r\n" /* Uncoditionally increment dst */ | ||
501 | "cmp %[px], %[fgcolor] \r\n" /* Compare to foreground color */ | ||
502 | "streqh %[fgpat], [%[d], #-2] \r\n" /* Store foregroud if match */ | ||
503 | "cmpne %[px], %[transcolor] \r\n" /* Compare to transparent color */ | ||
504 | "strneh %[px], [%[d], #-2] \r\n" /* Store dst if not transparent */ | ||
505 | "subs %[w], %[w], #1 \r\n" /* Width counter has run down? */ | ||
506 | "bgt .nextpixel \r\n" /* More in this row? */ | ||
507 | "add %[s], %[s], %[sstp], lsl #1 \r\n" /* Skip over to start of next line */ | ||
508 | "add %[d], %[d], %[dstp], lsl #1 \r\n" | ||
509 | "subs %[h], %[h], #1 \r\n" /* Height counter has run down? */ | ||
510 | "bgt .rowstart \r\n" /* More rows? */ | ||
511 | : [w]"=&r"(w), [h]"+&r"(height), [px]"=&r"(px), | ||
512 | [s]"+&r"(src), [d]"+&r"(dst) | ||
513 | : [width]"r"(width), | ||
514 | [sstp]"r"(stride - width), | ||
515 | [dstp]"r"(LCD_WIDTH - width), | ||
516 | [transcolor]"r"(TRANSPARENT_COLOR), | ||
517 | [fgcolor]"r"(REPLACEWITHFG_COLOR), | ||
518 | [fgpat]"r"(current_vp->fg_pattern) | ||
519 | ); | ||
520 | } | ||
521 | #endif | ||
522 | |||
523 | void lcd_yuv_set_options(unsigned options) | 458 | void lcd_yuv_set_options(unsigned options) |
524 | { | 459 | { |
525 | lcd_yuv_options = options; | 460 | lcd_yuv_options = options; |