summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2009-10-26 01:35:31 +0000
committerJens Arnold <amiconn@rockbox.org>2009-10-26 01:35:31 +0000
commit5365cbe0a5af0ef357e7fc70e793141ccd38f23e (patch)
tree9682db5ae001f4fee09f9ba9bea4e650fdc96d97
parentdd0afc5aa28ab5117056dda3cb19a283ece56ef4 (diff)
downloadrockbox-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.c119
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/lcd-imx31.c63
-rw-r--r--firmware/target/arm/s3c2440/lcd-s3c2440.c65
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 */
838void ICODE_ATTR lcd_bitmap_transparent_part(const fb_data *src, int src_x, 838void 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 */
889void lcd_bitmap_transparent(const fb_data *src, int x, int y, 930void 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
149void 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
212void lcd_yuv_set_options(unsigned options) 149void 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)
459void 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
523void lcd_yuv_set_options(unsigned options) 458void lcd_yuv_set_options(unsigned options)
524{ 459{
525 lcd_yuv_options = options; 460 lcd_yuv_options = options;