diff options
author | Dave Chapman <dave@dchapman.com> | 2007-04-06 09:34:13 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2007-04-06 09:34:13 +0000 |
commit | 4303ab02a3efbd6a77e809641617c53082f9366f (patch) | |
tree | 73b2bde0cb847785981b69dc749d7223d2ae7a12 /firmware/target/arm | |
parent | 31d8068b331af435c50cacfbb0ed2de1c2221f4d (diff) | |
download | rockbox-4303ab02a3efbd6a77e809641617c53082f9366f.tar.gz rockbox-4303ab02a3efbd6a77e809641617c53082f9366f.zip |
Optimized lcd_yuv_blit() (used by mpegplayer) for the Sansa E200. This is just a copy-and-paste of the Gigabeat version by Michael Sevakis with no attempt to adapt to the different CPU in the E200 - so there could be room for further improvement. Reported to increase the FPS for the 224x128 version of Elephants Dream from 21fps to 27fps.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13042 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/lcd-as-e200.S | 222 | ||||
-rw-r--r-- | firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | 138 |
2 files changed, 256 insertions, 104 deletions
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-as-e200.S b/firmware/target/arm/sandisk/sansa-e200/lcd-as-e200.S new file mode 100644 index 0000000000..9e130cf54b --- /dev/null +++ b/firmware/target/arm/sandisk/sansa-e200/lcd-as-e200.S | |||
@@ -0,0 +1,222 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2007 by Michael Sevakis | ||
11 | * | ||
12 | * All files in this archive are subject to the GNU General Public License. | ||
13 | * See the file COPYING in the source tree root for full license agreement. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | |||
20 | #include "config.h" | ||
21 | #include "cpu.h" | ||
22 | |||
23 | /**************************************************************************** | ||
24 | * void lcd_write_yuv_420_lines(fb_data *dst, | ||
25 | * unsigned char chroma_buf[LCD_HEIGHT/2*3], | ||
26 | unsigned char const * const src[3], | ||
27 | * int width, | ||
28 | * int stride); | ||
29 | * | ||
30 | * |R| |1.000000 -0.000001 1.402000| |Y'| | ||
31 | * |G| = |1.000000 -0.334136 -0.714136| |Pb| | ||
32 | * |B| |1.000000 1.772000 0.000000| |Pr| | ||
33 | * Scaled, normalized, rounded and tweaked to yield RGB 565: | ||
34 | * |R| |74 0 101| |Y' - 16| >> 9 | ||
35 | * |G| = |74 -24 -51| |Cb - 128| >> 8 | ||
36 | * |B| |74 128 0| |Cr - 128| >> 9 | ||
37 | */ | ||
38 | .section .icode, "ax", %progbits | ||
39 | .align 2 | ||
40 | .global lcd_write_yuv420_lines | ||
41 | .type lcd_write_yuv420_lines, %function | ||
42 | lcd_write_yuv420_lines: | ||
43 | @ r0 = dst | ||
44 | @ r1 = chroma_buf | ||
45 | @ r2 = yuv_src | ||
46 | @ r3 = width | ||
47 | @ [sp] = stride | ||
48 | stmdb sp!, { r4-r12, lr } @ save non-scratch | ||
49 | stmdb sp!, { r0, r3 } @ save dst and width | ||
50 | mov r14, #74 @ r14 = Y factor | ||
51 | ldmia r2, { r4, r5, r6 } @ r4 = yuv_src[0] = Y'_p | ||
52 | @ r5 = yuv_src[1] = Cb_p | ||
53 | @ r6 = yuv_src[2] = Cr_p | ||
54 | 10: @ loop line 1 @ | ||
55 | ldrb r2, [r4], #1 @ r2 = *Y'_p++; | ||
56 | ldrb r8, [r5], #1 @ r8 = *Cb_p++; | ||
57 | ldrb r11, [r6], #1 @ r11 = *Cr_p++; | ||
58 | @ | ||
59 | @ compute Y | ||
60 | sub r2, r2, #16 @ r7 = Y = (Y' - 16)*74 | ||
61 | mul r7, r2, r14 @ | ||
62 | @ | ||
63 | sub r8, r8, #128 @ Cb -= 128 | ||
64 | sub r11, r11, #128 @ Cr -= 128 | ||
65 | @ | ||
66 | mvn r2, #24 @ compute guv | ||
67 | mul r10, r2, r8 @ r10 = Cb*-24 | ||
68 | mvn r2, #51 @ | ||
69 | mla r10, r2, r11, r10 @ r10 = r10 + Cr*-51 | ||
70 | @ | ||
71 | mov r2, #101 @ compute rv | ||
72 | mul r9, r11, r2 @ r9 = rv = Cr*101 | ||
73 | @ | ||
74 | @ store chromas in line buffer | ||
75 | add r8, r8, #2 @ bu = (Cb + 2) >> 2 | ||
76 | mov r8, r8, asr #2 @ | ||
77 | strb r8, [r1], #1 @ | ||
78 | add r9, r9, #256 @ rv = (Cr + 256) >> 9 | ||
79 | mov r9, r9, asr #9 @ | ||
80 | strb r9, [r1], #1 @ | ||
81 | mov r10, r10, asr #8 @ guv >>= 8 | ||
82 | strb r10, [r1], #1 @ | ||
83 | @ compute R, G, and B | ||
84 | add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu | ||
85 | add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv | ||
86 | add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv | ||
87 | @ | ||
88 | orr r12, r2, r11 @ check if clamping is needed... | ||
89 | orr r12, r12, r7, asr #1 @ ...at all | ||
90 | cmp r12, #31 @ | ||
91 | bls 15f @ no clamp @ | ||
92 | mov r12, #31 @ | ||
93 | cmp r12, r2 @ clamp b | ||
94 | andlo r2, r12, r2, asr #31 @ | ||
95 | eorlo r2, r2, r12 @ | ||
96 | cmp r12, r11 @ clamp r | ||
97 | andlo r11, r12, r11, asr #31 @ | ||
98 | eorlo r11, r11, r12 @ | ||
99 | cmp r12, r7, asr #1 @ clamp g | ||
100 | andlo r7, r12, r7, asr #31 @ | ||
101 | eorlo r7, r7, r12 @ | ||
102 | orrlo r7, r7, r7, asl #1 @ | ||
103 | 15: @ no clamp @ | ||
104 | @ | ||
105 | orr r12, r2, r7, lsl #5 @ r4 |= (g << 5) | ||
106 | ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++ | ||
107 | orr r12, r12, r11, lsl #11 @ r4 = b | (r << 11) | ||
108 | strh r12, [r0], #LCD_WIDTH @ store pixel | ||
109 | @ | ||
110 | sub r2, r2, #16 @ r7 = Y = (Y' - 16)*74 | ||
111 | mul r7, r2, r14 @ next Y | ||
112 | @ compute R, G, and B | ||
113 | add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu | ||
114 | add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv | ||
115 | add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv | ||
116 | @ | ||
117 | orr r12, r2, r11 @ check if clamping is needed... | ||
118 | orr r12, r12, r7, asr #1 @ ...at all | ||
119 | cmp r12, #31 @ | ||
120 | bls 15f @ no clamp @ | ||
121 | mov r12, #31 @ | ||
122 | cmp r12, r2 @ clamp b | ||
123 | andlo r2, r12, r2, asr #31 @ | ||
124 | eorlo r2, r2, r12 @ | ||
125 | cmp r12, r11 @ clamp r | ||
126 | andlo r11, r12, r11, asr #31 @ | ||
127 | eorlo r11, r11, r12 @ | ||
128 | cmp r12, r7, asr #1 @ clamp g | ||
129 | andlo r7, r12, r7, asr #31 @ | ||
130 | eorlo r7, r7, r12 @ | ||
131 | orrlo r7, r7, r7, asl #1 @ | ||
132 | 15: @ no clamp @ | ||
133 | @ | ||
134 | orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) | ||
135 | orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) | ||
136 | strh r12, [r0, #LCD_WIDTH]! @ store pixel | ||
137 | add r0, r0, #2*LCD_WIDTH @ | ||
138 | @ | ||
139 | subs r3, r3, #2 @ | ||
140 | bgt 10b @ loop line 1 @ | ||
141 | @ do second line | ||
142 | @ | ||
143 | ldmia sp!, { r0, r3 } @ pop dst and width | ||
144 | sub r0, r0, #2 @ set dst to start of next line | ||
145 | sub r1, r1, r3, asl #1 @ rewind chroma pointer... | ||
146 | ldr r2, [sp, #40] @ r2 = stride | ||
147 | add r1, r1, r3, asr #1 @ ... (r1 -= width/2*3) | ||
148 | @ move sources to start of next line | ||
149 | sub r2, r2, r3 @ r2 = skip = stride - width | ||
150 | add r4, r4, r2 @ r4 = Y'_p + skip | ||
151 | @ | ||
152 | 20: @ loop line 2 @ | ||
153 | ldrb r2, [r4], #1 @ r7 = Y' = *Y'_p++ | ||
154 | ldrsb r8, [r1], #1 @ reload saved chromas | ||
155 | ldrsb r9, [r1], #1 @ | ||
156 | ldrsb r10, [r1], #1 @ | ||
157 | @ | ||
158 | sub r2, r2, #16 @ r2 = Y = (Y' - 16)*74 | ||
159 | mul r7, r2, r14 @ | ||
160 | @ compute R, G, and B | ||
161 | add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu | ||
162 | add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv | ||
163 | add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv | ||
164 | @ | ||
165 | orr r12, r2, r11 @ check if clamping is needed... | ||
166 | orr r12, r12, r7, asr #1 @ ...at all | ||
167 | cmp r12, #31 @ | ||
168 | bls 25f @ no clamp @ | ||
169 | mov r12, #31 @ | ||
170 | cmp r12, r2 @ clamp b | ||
171 | andlo r2, r12, r2, asr #31 @ | ||
172 | eorlo r2, r2, r12 @ | ||
173 | cmp r12, r11 @ clamp r | ||
174 | andlo r11, r12, r11, asr #31 @ | ||
175 | eorlo r11, r11, r12 @ | ||
176 | cmp r12, r7, asr #1 @ clamp g | ||
177 | andlo r7, r12, r7, asr #31 @ | ||
178 | eorlo r7, r7, r12 @ | ||
179 | orrlo r7, r7, r7, asl #1 @ | ||
180 | 25: @ no clamp @ | ||
181 | @ | ||
182 | orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) | ||
183 | ldrb r2, [r4], #1 @ r2 = Y' = *Y'_p++ | ||
184 | orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) | ||
185 | strh r12, [r0], #LCD_WIDTH @ store pixel | ||
186 | @ | ||
187 | @ do second pixel | ||
188 | @ | ||
189 | sub r2, r2, #16 @ r2 = Y = (Y' - 16)*74 | ||
190 | mul r7, r2, r14 @ | ||
191 | @ compute R, G, and B | ||
192 | add r2, r8, r7, asr #9 @ r2 = b = (Y >> 9) + bu | ||
193 | add r11, r9, r7, asr #9 @ r11 = r = (Y >> 9) + rv | ||
194 | add r7, r10, r7, asr #8 @ r7 = g = (Y >> 8) + guv | ||
195 | @ | ||
196 | orr r12, r2, r11 @ check if clamping is needed... | ||
197 | orr r12, r12, r7, asr #1 @ ...at all | ||
198 | cmp r12, #31 @ | ||
199 | bls 25f @ no clamp @ | ||
200 | mov r12, #31 @ | ||
201 | cmp r12, r2 @ clamp b | ||
202 | andlo r2, r12, r2, asr #31 @ | ||
203 | eorlo r2, r2, r12 @ | ||
204 | cmp r12, r11 @ clamp r | ||
205 | andlo r11, r12, r11, asr #31 @ | ||
206 | eorlo r11, r11, r12 @ | ||
207 | cmp r12, r7, asr #1 @ clamp g | ||
208 | andlo r7, r12, r7, asr #31 @ | ||
209 | eorlo r7, r7, r12 @ | ||
210 | orrlo r7, r7, r7, asl #1 @ | ||
211 | 25: @ no clamp @ | ||
212 | @ | ||
213 | orr r12, r2, r11, lsl #11 @ r4 = b | (r << 11) | ||
214 | orr r12, r12, r7, lsl #5 @ r4 |= (g << 5) | ||
215 | strh r12, [r0, #LCD_WIDTH]! @ store pixel | ||
216 | add r0, r0, #2*LCD_WIDTH @ | ||
217 | @ | ||
218 | subs r3, r3, #2 @ | ||
219 | bgt 20b @ loop line 2 @ | ||
220 | @ | ||
221 | ldmia sp!, { r4-r12, pc } @ restore registers and return | ||
222 | .size lcd_write_yuv420_lines, .-lcd_write_yuv420_lines | ||
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c index 6b51531056..3e8246b367 100644 --- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c +++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c | |||
@@ -329,115 +329,45 @@ void lcd_blit(const fb_data* data, int x, int by, int width, | |||
329 | (void)stride; | 329 | (void)stride; |
330 | } | 330 | } |
331 | 331 | ||
332 | #define CSUB_X 2 | 332 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ |
333 | #define CSUB_Y 2 | 333 | extern void lcd_write_yuv420_lines(fb_data *dst, |
334 | 334 | unsigned char chroma_buf[LCD_HEIGHT/2*3], | |
335 | #define RYFAC (31*257) | 335 | unsigned char const * const src[3], |
336 | #define GYFAC (63*257) | 336 | int width, |
337 | #define BYFAC (31*257) | 337 | int stride); |
338 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | 338 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
339 | #define GVFAC (-11563) /* 63 * 257 * -0.714136 */ | 339 | /* For the e200 - show it rotated */ |
340 | #define GUFAC (-5572) /* 63 * 257 * -0.344136 */ | 340 | /* So the LCD_WIDTH is now the height */ |
341 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | ||
342 | |||
343 | #define ROUNDOFFS (127*257) | ||
344 | |||
345 | /* Performance function to blit a YUV bitmap directly to the LCD | ||
346 | Actually this code is from gigabeat, because this target is also | ||
347 | writing direct to a buffer. */ | ||
348 | void lcd_yuv_blit(unsigned char * const src[3], | 341 | void lcd_yuv_blit(unsigned char * const src[3], |
349 | int src_x, int src_y, int stride, | 342 | int src_x, int src_y, int stride, |
350 | int _x, int _y, int width, int height) | 343 | int x, int y, int width, int height) |
351 | { | 344 | { |
352 | const unsigned char *usrc; | 345 | /* Caches for chroma data so it only need be recaculated every other |
353 | const unsigned char *vsrc; | 346 | line */ |
354 | const unsigned char *ysrc; | 347 | unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */ |
355 | int xphase; | 348 | unsigned char const * yuv_src[3]; |
356 | int rc, gc, bc; | 349 | off_t z; |
357 | int y, u, v; | 350 | |
358 | int red, green, blue; | 351 | /* Sorry, but width and height must be >= 2 or else */ |
359 | unsigned rbits, gbits, bbits; | 352 | width &= ~1; |
360 | int count; | 353 | height >>= 1; |
361 | fb_data *dst_row; | 354 | |
362 | |||
363 | |||
364 | width = (width + 1) & ~1; | ||
365 | fb_data *dst = (fb_data*)lcd_driver_framebuffer + | 355 | fb_data *dst = (fb_data*)lcd_driver_framebuffer + |
366 | _x * LCD_WIDTH + (LCD_WIDTH - _y) - 1; | 356 | x * LCD_WIDTH + (LCD_WIDTH - y) - 1; |
367 | fb_data *dst_last = dst - (height - 1); | 357 | |
358 | z = stride*src_y; | ||
359 | yuv_src[0] = src[0] + z + src_x; | ||
360 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
361 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
368 | 362 | ||
369 | do | 363 | do |
370 | { | 364 | { |
371 | dst_row = dst; | 365 | lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width, |
372 | count = width; | 366 | stride); |
373 | ysrc = src[0] + stride * src_y + src_x; | 367 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ |
374 | 368 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | |
375 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | 369 | yuv_src[2] += stride >> 1; |
376 | usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y) | 370 | dst -= 2; |
377 | + (src_x/CSUB_X); | 371 | } |
378 | vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y) | 372 | while (--height > 0); |
379 | + (src_x/CSUB_X); | ||
380 | xphase = src_x % CSUB_X; | ||
381 | |||
382 | u = *usrc++ - 128; | ||
383 | v = *vsrc++ - 128; | ||
384 | rc = RVFAC * v + ROUNDOFFS; | ||
385 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | ||
386 | bc = BUFAC * u + ROUNDOFFS; | ||
387 | |||
388 | do | ||
389 | { | ||
390 | y = *ysrc++; | ||
391 | red = RYFAC * y + rc; | ||
392 | green = GYFAC * y + gc; | ||
393 | blue = BYFAC * y + bc; | ||
394 | |||
395 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | ||
396 | { | ||
397 | if (red < 0) | ||
398 | red = 0; | ||
399 | else | ||
400 | red = (RYFAC*255+ROUNDOFFS); | ||
401 | } | ||
402 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | ||
403 | { | ||
404 | if (green < 0) | ||
405 | green = 0; | ||
406 | else | ||
407 | green = (GYFAC*255+ROUNDOFFS); | ||
408 | } | ||
409 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | ||
410 | { | ||
411 | if (blue < 0) | ||
412 | blue = 0; | ||
413 | else | ||
414 | blue = (BYFAC*255+ROUNDOFFS); | ||
415 | } | ||
416 | rbits = ((unsigned)red) >> 16 ; | ||
417 | gbits = ((unsigned)green) >> 16 ; | ||
418 | bbits = ((unsigned)blue) >> 16 ; | ||
419 | |||
420 | *dst_row = (rbits << 11) | (gbits << 5) | bbits; | ||
421 | |||
422 | /* next pixel - since rotated, add WIDTH */ | ||
423 | dst_row += LCD_WIDTH; | ||
424 | |||
425 | if (++xphase >= CSUB_X) | ||
426 | { | ||
427 | u = *usrc++ - 128; | ||
428 | v = *vsrc++ - 128; | ||
429 | rc = RVFAC * v + ROUNDOFFS; | ||
430 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | ||
431 | bc = BUFAC * u + ROUNDOFFS; | ||
432 | xphase = 0; | ||
433 | } | ||
434 | } | ||
435 | while (--count); | ||
436 | |||
437 | if (dst == dst_last) break; | ||
438 | |||
439 | dst--; | ||
440 | src_y++; | ||
441 | } while( 1); | ||
442 | } | 373 | } |
443 | |||