diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2007-04-02 09:27:12 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2007-04-02 09:27:12 +0000 |
commit | 6f56607212ae8d2e0ce637553bb9068f84e01798 (patch) | |
tree | 8ef278bab8748ac6a85599f95f059aec0d712739 /firmware/target/arm | |
parent | fef40e465abe7ddfc5895bf2547a3f004eaa9b5c (diff) | |
download | rockbox-6f56607212ae8d2e0ce637553bb9068f84e01798.tar.gz rockbox-6f56607212ae8d2e0ce637553bb9068f84e01798.zip |
Gigabeat: Add an assembly lcd_yuv_blit. Seems to be good for a modest speedup. ;)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12998 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/gigabeat/meg-fx/lcd-as-meg-fx.S | 222 | ||||
-rw-r--r-- | firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c | 126 |
2 files changed, 254 insertions, 94 deletions
diff --git a/firmware/target/arm/gigabeat/meg-fx/lcd-as-meg-fx.S b/firmware/target/arm/gigabeat/meg-fx/lcd-as-meg-fx.S new file mode 100644 index 0000000000..414f26d3c5 --- /dev/null +++ b/firmware/target/arm/gigabeat/meg-fx/lcd-as-meg-fx.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[3][LCD_HEIGHT/2], | ||
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], #240 @ 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, #240]! @ store pixel | ||
137 | add r0, r0, #2*240 @ | ||
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], #240 @ 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, #240]! @ store pixel | ||
216 | add r0, r0, #2*240 @ | ||
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/gigabeat/meg-fx/lcd-meg-fx.c b/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c index 2d2f32069a..1bb68f9686 100644 --- a/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c +++ b/firmware/target/arm/gigabeat/meg-fx/lcd-meg-fx.c | |||
@@ -293,22 +293,12 @@ void lcd_bitmap_transparent_part(const fb_data *src, int src_x, int src_y, | |||
293 | : : "r" (src), "r" (dst), "r" (width), "r" (dst_end), "r" (stride), "r" (transcolor) : "r0", "r1" ); | 293 | : : "r" (src), "r" (dst), "r" (width), "r" (dst_end), "r" (stride), "r" (transcolor) : "r0", "r1" ); |
294 | } | 294 | } |
295 | 295 | ||
296 | #define CSUB_X 2 | 296 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ |
297 | #define CSUB_Y 2 | 297 | extern void lcd_write_yuv420_lines(fb_data *dst, |
298 | 298 | unsigned char chroma_buf[LCD_HEIGHT/2*3], | |
299 | #define RFULL (31*257) | 299 | unsigned char const * const src[3], |
300 | #define GFULL (63*257) | 300 | int width, |
301 | #define BFULL (31*257) | 301 | int stride); |
302 | #define RYFAC 9277 /* 31 * 257 * 1.0 * (255/219) */ | ||
303 | #define GYFAC 18853 /* 63 * 257 * 1.0 * (255/219) */ | ||
304 | #define BYFAC 9277 /* 31 * 257 * 1.0 * (255/219) */ | ||
305 | #define RVFAC 12716 /* 31 * 257 * 1.402 * (255/224) */ | ||
306 | #define GVFAC (-13163) /* 63 * 257 * -0.714136 * (255/224) */ | ||
307 | #define GUFAC (-6343) /* 63 * 257 * -0.344136 * (255/224) */ | ||
308 | #define BUFAC 16071 /* 31 * 257 * 1.772 * (255/224) */ | ||
309 | |||
310 | #define ROUNDOFFS (127*257) | ||
311 | |||
312 | /* Performance function to blit a YUV bitmap directly to the LCD */ | 302 | /* Performance function to blit a YUV bitmap directly to the LCD */ |
313 | /* For the Gigabeat - show it rotated */ | 303 | /* For the Gigabeat - show it rotated */ |
314 | /* So the LCD_WIDTH is now the height */ | 304 | /* So the LCD_WIDTH is now the height */ |
@@ -316,90 +306,38 @@ void lcd_yuv_blit(unsigned char * const src[3], | |||
316 | int src_x, int src_y, int stride, | 306 | int src_x, int src_y, int stride, |
317 | int x, int y, int width, int height) | 307 | int x, int y, int width, int height) |
318 | { | 308 | { |
319 | width = (width + 1) & ~1; | 309 | /* Caches for chroma data so it only need be recaculated every other |
320 | fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1; | 310 | line */ |
321 | fb_data *dst_last = dst - (height - 1); | 311 | unsigned char chroma_buf[LCD_HEIGHT/2*3]; /* 480 bytes */ |
312 | unsigned char const * yuv_src[3]; | ||
313 | off_t z; | ||
322 | 314 | ||
323 | for (;;) | 315 | if (!lcd_on) |
324 | { | 316 | return; |
325 | fb_data *dst_row = dst; | ||
326 | int count = width; | ||
327 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | ||
328 | int y, u, v; | ||
329 | int red, green, blue; | ||
330 | unsigned rbits, gbits, bbits; | ||
331 | |||
332 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | ||
333 | const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y) | ||
334 | + (src_x/CSUB_X); | ||
335 | const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y) | ||
336 | + (src_x/CSUB_X); | ||
337 | int xphase = src_x % CSUB_X; | ||
338 | int rc, gc, bc; | ||
339 | |||
340 | u = *usrc++ - 128; | ||
341 | v = *vsrc++ - 128; | ||
342 | rc = RVFAC * v + ROUNDOFFS; | ||
343 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | ||
344 | bc = BUFAC * u + ROUNDOFFS; | ||
345 | |||
346 | do | ||
347 | { | ||
348 | y = *ysrc++ - 16; | ||
349 | red = RYFAC * y + rc; | ||
350 | green = GYFAC * y + gc; | ||
351 | blue = BYFAC * y + bc; | ||
352 | |||
353 | if ((unsigned)red > (RFULL*255+ROUNDOFFS)) | ||
354 | { | ||
355 | if (red < 0) | ||
356 | red = 0; | ||
357 | else | ||
358 | red = (RFULL*255+ROUNDOFFS); | ||
359 | } | ||
360 | if ((unsigned)green > (GFULL*255+ROUNDOFFS)) | ||
361 | { | ||
362 | if (green < 0) | ||
363 | green = 0; | ||
364 | else | ||
365 | green = (GFULL*255+ROUNDOFFS); | ||
366 | } | ||
367 | if ((unsigned)blue > (BFULL*255+ROUNDOFFS)) | ||
368 | { | ||
369 | if (blue < 0) | ||
370 | blue = 0; | ||
371 | else | ||
372 | blue = (BFULL*255+ROUNDOFFS); | ||
373 | } | ||
374 | rbits = ((unsigned)red) >> 16 ; | ||
375 | gbits = ((unsigned)green) >> 16 ; | ||
376 | bbits = ((unsigned)blue) >> 16 ; | ||
377 | |||
378 | *dst_row = (rbits << 11) | (gbits << 5) | bbits; | ||
379 | |||
380 | /* next pixel - since rotated, add WIDTH */ | ||
381 | dst_row += LCD_WIDTH; | ||
382 | |||
383 | if (++xphase >= CSUB_X) | ||
384 | { | ||
385 | u = *usrc++ - 128; | ||
386 | v = *vsrc++ - 128; | ||
387 | rc = RVFAC * v + ROUNDOFFS; | ||
388 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | ||
389 | bc = BUFAC * u + ROUNDOFFS; | ||
390 | xphase = 0; | ||
391 | } | ||
392 | } | ||
393 | while (--count); | ||
394 | 317 | ||
395 | if (dst == dst_last) break; | 318 | /* Sorry, but width and height must be >= 2 or else */ |
319 | width &= ~1; | ||
320 | height >>= 1; | ||
396 | 321 | ||
397 | dst--; | 322 | fb_data *dst = (fb_data*)FRAME + x * LCD_WIDTH + (LCD_WIDTH - y) - 1; |
398 | src_y++; | 323 | |
324 | z = stride*src_y; | ||
325 | yuv_src[0] = src[0] + z + src_x; | ||
326 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
327 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
328 | |||
329 | do | ||
330 | { | ||
331 | lcd_write_yuv420_lines(dst, chroma_buf, yuv_src, width, | ||
332 | stride); | ||
333 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
334 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
335 | yuv_src[2] += stride >> 1; | ||
336 | dst -= 2; | ||
399 | } | 337 | } |
338 | while (--height > 0); | ||
400 | } | 339 | } |
401 | 340 | ||
402 | |||
403 | void lcd_set_contrast(int val) { | 341 | void lcd_set_contrast(int val) { |
404 | (void) val; | 342 | (void) val; |
405 | // TODO: | 343 | // TODO: |